The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

551 lines
17KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. #include "../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_AudioFormat.h"
  21. #include "../dsp/juce_AudioSampleBuffer.h"
  22. //==============================================================================
  23. AudioFormatReader::AudioFormatReader (InputStream* const in,
  24. const String& formatName_)
  25. : sampleRate (0),
  26. bitsPerSample (0),
  27. lengthInSamples (0),
  28. numChannels (0),
  29. usesFloatingPointData (false),
  30. input (in),
  31. formatName (formatName_)
  32. {
  33. }
  34. AudioFormatReader::~AudioFormatReader()
  35. {
  36. delete input;
  37. }
  38. bool AudioFormatReader::read (int** destSamples,
  39. int numDestChannels,
  40. int64 startSampleInSource,
  41. int numSamplesToRead,
  42. const bool fillLeftoverChannelsWithCopies)
  43. {
  44. jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
  45. int startOffsetInDestBuffer = 0;
  46. if (startSampleInSource < 0)
  47. {
  48. const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
  49. for (int i = numDestChannels; --i >= 0;)
  50. if (destSamples[i] != 0)
  51. zeromem (destSamples[i], sizeof (int) * silence);
  52. startOffsetInDestBuffer += silence;
  53. numSamplesToRead -= silence;
  54. startSampleInSource = 0;
  55. }
  56. if (numSamplesToRead <= 0)
  57. return true;
  58. if (! readSamples (destSamples, jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer,
  59. startSampleInSource, numSamplesToRead))
  60. return false;
  61. if (numDestChannels > (int) numChannels)
  62. {
  63. if (fillLeftoverChannelsWithCopies)
  64. {
  65. int* lastFullChannel = destSamples[0];
  66. for (int i = numDestChannels; --i > 0;)
  67. {
  68. if (destSamples[i] != 0)
  69. {
  70. lastFullChannel = destSamples[i];
  71. break;
  72. }
  73. }
  74. if (lastFullChannel != 0)
  75. for (int i = numChannels; i < numDestChannels; ++i)
  76. if (destSamples[i] != 0)
  77. memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead);
  78. }
  79. else
  80. {
  81. for (int i = numChannels; i < numDestChannels; ++i)
  82. if (destSamples[i] != 0)
  83. zeromem (destSamples[i], sizeof (int) * numSamplesToRead);
  84. }
  85. }
  86. return true;
  87. }
  88. static void findAudioBufferMaxMin (const float* const buffer, const int num, float& maxVal, float& minVal) throw()
  89. {
  90. float mn = buffer[0];
  91. float mx = mn;
  92. for (int i = 1; i < num; ++i)
  93. {
  94. const float s = buffer[i];
  95. if (s > mx) mx = s;
  96. if (s < mn) mn = s;
  97. }
  98. maxVal = mx;
  99. minVal = mn;
  100. }
  101. void AudioFormatReader::readMaxLevels (int64 startSampleInFile,
  102. int64 numSamples,
  103. float& lowestLeft, float& highestLeft,
  104. float& lowestRight, float& highestRight)
  105. {
  106. if (numSamples <= 0)
  107. {
  108. lowestLeft = 0;
  109. lowestRight = 0;
  110. highestLeft = 0;
  111. highestRight = 0;
  112. return;
  113. }
  114. const int bufferSize = (int) jmin (numSamples, (int64) 4096);
  115. MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
  116. int* tempBuffer[3];
  117. tempBuffer[0] = (int*) tempSpace.getData();
  118. tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
  119. tempBuffer[2] = 0;
  120. if (usesFloatingPointData)
  121. {
  122. float lmin = 1.0e6f;
  123. float lmax = -lmin;
  124. float rmin = lmin;
  125. float rmax = lmax;
  126. while (numSamples > 0)
  127. {
  128. const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
  129. read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
  130. numSamples -= numToDo;
  131. startSampleInFile += numToDo;
  132. float bufmin, bufmax;
  133. findAudioBufferMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin);
  134. lmin = jmin (lmin, bufmin);
  135. lmax = jmax (lmax, bufmax);
  136. if (numChannels > 1)
  137. {
  138. findAudioBufferMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin);
  139. rmin = jmin (rmin, bufmin);
  140. rmax = jmax (rmax, bufmax);
  141. }
  142. }
  143. if (numChannels <= 1)
  144. {
  145. rmax = lmax;
  146. rmin = lmin;
  147. }
  148. lowestLeft = lmin;
  149. highestLeft = lmax;
  150. lowestRight = rmin;
  151. highestRight = rmax;
  152. }
  153. else
  154. {
  155. int lmax = std::numeric_limits<int>::min();
  156. int lmin = std::numeric_limits<int>::max();
  157. int rmax = std::numeric_limits<int>::min();
  158. int rmin = std::numeric_limits<int>::max();
  159. while (numSamples > 0)
  160. {
  161. const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
  162. read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
  163. numSamples -= numToDo;
  164. startSampleInFile += numToDo;
  165. for (int j = numChannels; --j >= 0;)
  166. {
  167. int bufMax = std::numeric_limits<int>::min();
  168. int bufMin = std::numeric_limits<int>::max();
  169. const int* const b = tempBuffer[j];
  170. for (int i = 0; i < numToDo; ++i)
  171. {
  172. const int samp = b[i];
  173. if (samp < bufMin)
  174. bufMin = samp;
  175. if (samp > bufMax)
  176. bufMax = samp;
  177. }
  178. if (j == 0)
  179. {
  180. lmax = jmax (lmax, bufMax);
  181. lmin = jmin (lmin, bufMin);
  182. }
  183. else
  184. {
  185. rmax = jmax (rmax, bufMax);
  186. rmin = jmin (rmin, bufMin);
  187. }
  188. }
  189. }
  190. if (numChannels <= 1)
  191. {
  192. rmax = lmax;
  193. rmin = lmin;
  194. }
  195. lowestLeft = lmin / (float) std::numeric_limits<int>::max();
  196. highestLeft = lmax / (float) std::numeric_limits<int>::max();
  197. lowestRight = rmin / (float) std::numeric_limits<int>::max();
  198. highestRight = rmax / (float) std::numeric_limits<int>::max();
  199. }
  200. }
  201. int64 AudioFormatReader::searchForLevel (int64 startSample,
  202. int64 numSamplesToSearch,
  203. const double magnitudeRangeMinimum,
  204. const double magnitudeRangeMaximum,
  205. const int minimumConsecutiveSamples)
  206. {
  207. if (numSamplesToSearch == 0)
  208. return -1;
  209. const int bufferSize = 4096;
  210. MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
  211. int* tempBuffer[3];
  212. tempBuffer[0] = (int*) tempSpace.getData();
  213. tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
  214. tempBuffer[2] = 0;
  215. int consecutive = 0;
  216. int64 firstMatchPos = -1;
  217. jassert (magnitudeRangeMaximum > magnitudeRangeMinimum);
  218. const double doubleMin = jlimit (0.0, (double) std::numeric_limits<int>::max(), magnitudeRangeMinimum * std::numeric_limits<int>::max());
  219. const double doubleMax = jlimit (doubleMin, (double) std::numeric_limits<int>::max(), magnitudeRangeMaximum * std::numeric_limits<int>::max());
  220. const int intMagnitudeRangeMinimum = roundToInt (doubleMin);
  221. const int intMagnitudeRangeMaximum = roundToInt (doubleMax);
  222. while (numSamplesToSearch != 0)
  223. {
  224. const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize);
  225. int64 bufferStart = startSample;
  226. if (numSamplesToSearch < 0)
  227. bufferStart -= numThisTime;
  228. if (bufferStart >= (int) lengthInSamples)
  229. break;
  230. read ((int**) tempBuffer, 2, bufferStart, numThisTime, false);
  231. int num = numThisTime;
  232. while (--num >= 0)
  233. {
  234. if (numSamplesToSearch < 0)
  235. --startSample;
  236. bool matches = false;
  237. const int index = (int) (startSample - bufferStart);
  238. if (usesFloatingPointData)
  239. {
  240. const float sample1 = std::abs (((float*) tempBuffer[0]) [index]);
  241. if (sample1 >= magnitudeRangeMinimum
  242. && sample1 <= magnitudeRangeMaximum)
  243. {
  244. matches = true;
  245. }
  246. else if (numChannels > 1)
  247. {
  248. const float sample2 = std::abs (((float*) tempBuffer[1]) [index]);
  249. matches = (sample2 >= magnitudeRangeMinimum
  250. && sample2 <= magnitudeRangeMaximum);
  251. }
  252. }
  253. else
  254. {
  255. const int sample1 = abs (tempBuffer[0] [index]);
  256. if (sample1 >= intMagnitudeRangeMinimum
  257. && sample1 <= intMagnitudeRangeMaximum)
  258. {
  259. matches = true;
  260. }
  261. else if (numChannels > 1)
  262. {
  263. const int sample2 = abs (tempBuffer[1][index]);
  264. matches = (sample2 >= intMagnitudeRangeMinimum
  265. && sample2 <= intMagnitudeRangeMaximum);
  266. }
  267. }
  268. if (matches)
  269. {
  270. if (firstMatchPos < 0)
  271. firstMatchPos = startSample;
  272. if (++consecutive >= minimumConsecutiveSamples)
  273. {
  274. if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples)
  275. return -1;
  276. return firstMatchPos;
  277. }
  278. }
  279. else
  280. {
  281. consecutive = 0;
  282. firstMatchPos = -1;
  283. }
  284. if (numSamplesToSearch > 0)
  285. ++startSample;
  286. }
  287. if (numSamplesToSearch > 0)
  288. numSamplesToSearch -= numThisTime;
  289. else
  290. numSamplesToSearch += numThisTime;
  291. }
  292. return -1;
  293. }
  294. //==============================================================================
  295. AudioFormatWriter::AudioFormatWriter (OutputStream* const out,
  296. const String& formatName_,
  297. const double rate,
  298. const unsigned int numChannels_,
  299. const unsigned int bitsPerSample_)
  300. : sampleRate (rate),
  301. numChannels (numChannels_),
  302. bitsPerSample (bitsPerSample_),
  303. usesFloatingPointData (false),
  304. output (out),
  305. formatName (formatName_)
  306. {
  307. }
  308. AudioFormatWriter::~AudioFormatWriter()
  309. {
  310. delete output;
  311. }
  312. bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader,
  313. int64 startSample,
  314. int64 numSamplesToRead)
  315. {
  316. const int bufferSize = 16384;
  317. AudioSampleBuffer tempBuffer (numChannels, bufferSize);
  318. int* buffers [128];
  319. zerostruct (buffers);
  320. for (int i = tempBuffer.getNumChannels(); --i >= 0;)
  321. buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
  322. if (numSamplesToRead < 0)
  323. numSamplesToRead = reader.lengthInSamples;
  324. while (numSamplesToRead > 0)
  325. {
  326. const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
  327. if (! reader.read (buffers, numChannels, startSample, numToDo, false))
  328. return false;
  329. if (reader.usesFloatingPointData != isFloatingPoint())
  330. {
  331. int** bufferChan = buffers;
  332. while (*bufferChan != 0)
  333. {
  334. int* b = *bufferChan++;
  335. if (isFloatingPoint())
  336. {
  337. // int -> float
  338. const double factor = 1.0 / std::numeric_limits<int>::max();
  339. for (int i = 0; i < numToDo; ++i)
  340. ((float*) b)[i] = (float) (factor * b[i]);
  341. }
  342. else
  343. {
  344. // float -> int
  345. for (int i = 0; i < numToDo; ++i)
  346. {
  347. const double samp = *(const float*) b;
  348. if (samp <= -1.0)
  349. *b++ = std::numeric_limits<int>::min();
  350. else if (samp >= 1.0)
  351. *b++ = std::numeric_limits<int>::max();
  352. else
  353. *b++ = roundToInt (std::numeric_limits<int>::max() * samp);
  354. }
  355. }
  356. }
  357. }
  358. if (! write ((const int**) buffers, numToDo))
  359. return false;
  360. numSamplesToRead -= numToDo;
  361. startSample += numToDo;
  362. }
  363. return true;
  364. }
  365. bool AudioFormatWriter::writeFromAudioSource (AudioSource& source,
  366. int numSamplesToRead,
  367. const int samplesPerBlock)
  368. {
  369. AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock);
  370. int* buffers [128];
  371. zerostruct (buffers);
  372. for (int i = tempBuffer.getNumChannels(); --i >= 0;)
  373. buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
  374. while (numSamplesToRead > 0)
  375. {
  376. const int numToDo = jmin (numSamplesToRead, samplesPerBlock);
  377. AudioSourceChannelInfo info;
  378. info.buffer = &tempBuffer;
  379. info.startSample = 0;
  380. info.numSamples = numToDo;
  381. info.clearActiveBufferRegion();
  382. source.getNextAudioBlock (info);
  383. if (! isFloatingPoint())
  384. {
  385. int** bufferChan = buffers;
  386. while (*bufferChan != 0)
  387. {
  388. int* b = *bufferChan++;
  389. // float -> int
  390. for (int j = numToDo; --j >= 0;)
  391. {
  392. const double samp = *(const float*) b;
  393. if (samp <= -1.0)
  394. *b++ = std::numeric_limits<int>::min();
  395. else if (samp >= 1.0)
  396. *b++ = std::numeric_limits<int>::max();
  397. else
  398. *b++ = roundToInt (std::numeric_limits<int>::max() * samp);
  399. }
  400. }
  401. }
  402. if (! write ((const int**) buffers, numToDo))
  403. return false;
  404. numSamplesToRead -= numToDo;
  405. }
  406. return true;
  407. }
  408. //==============================================================================
  409. AudioFormat::AudioFormat (const String& name,
  410. const StringArray& extensions)
  411. : formatName (name),
  412. fileExtensions (extensions)
  413. {
  414. }
  415. AudioFormat::~AudioFormat()
  416. {
  417. }
  418. //==============================================================================
  419. const String& AudioFormat::getFormatName() const
  420. {
  421. return formatName;
  422. }
  423. const StringArray& AudioFormat::getFileExtensions() const
  424. {
  425. return fileExtensions;
  426. }
  427. bool AudioFormat::canHandleFile (const File& f)
  428. {
  429. for (int i = 0; i < fileExtensions.size(); ++i)
  430. if (f.hasFileExtension (fileExtensions[i]))
  431. return true;
  432. return false;
  433. }
  434. bool AudioFormat::isCompressed()
  435. {
  436. return false;
  437. }
  438. const StringArray AudioFormat::getQualityOptions()
  439. {
  440. return StringArray();
  441. }
  442. END_JUCE_NAMESPACE