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.

560 lines
17KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-9 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 (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 findMaxMin (const float* src, const int num,
  89. float& maxVal, float& minVal)
  90. {
  91. float mn = src[0];
  92. float mx = mn;
  93. for (int i = 1; i < num; ++i)
  94. {
  95. const float s = src[i];
  96. if (s > mx)
  97. mx = s;
  98. if (s < mn)
  99. mn = s;
  100. }
  101. maxVal = mx;
  102. minVal = mn;
  103. }
  104. void AudioFormatReader::readMaxLevels (int64 startSampleInFile,
  105. int64 numSamples,
  106. float& lowestLeft, float& highestLeft,
  107. float& lowestRight, float& highestRight)
  108. {
  109. if (numSamples <= 0)
  110. {
  111. lowestLeft = 0;
  112. lowestRight = 0;
  113. highestLeft = 0;
  114. highestRight = 0;
  115. return;
  116. }
  117. const int bufferSize = (int) jmin (numSamples, (int64) 4096);
  118. MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
  119. int* tempBuffer[3];
  120. tempBuffer[0] = (int*) tempSpace.getData();
  121. tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
  122. tempBuffer[2] = 0;
  123. if (usesFloatingPointData)
  124. {
  125. float lmin = 1.0e6f;
  126. float lmax = -lmin;
  127. float rmin = lmin;
  128. float rmax = lmax;
  129. while (numSamples > 0)
  130. {
  131. const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
  132. read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
  133. numSamples -= numToDo;
  134. startSampleInFile += numToDo;
  135. float bufmin, bufmax;
  136. findMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin);
  137. lmin = jmin (lmin, bufmin);
  138. lmax = jmax (lmax, bufmax);
  139. if (numChannels > 1)
  140. {
  141. findMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin);
  142. rmin = jmin (rmin, bufmin);
  143. rmax = jmax (rmax, bufmax);
  144. }
  145. }
  146. if (numChannels <= 1)
  147. {
  148. rmax = lmax;
  149. rmin = lmin;
  150. }
  151. lowestLeft = lmin;
  152. highestLeft = lmax;
  153. lowestRight = rmin;
  154. highestRight = rmax;
  155. }
  156. else
  157. {
  158. int lmax = INT_MIN;
  159. int lmin = INT_MAX;
  160. int rmax = INT_MIN;
  161. int rmin = INT_MAX;
  162. while (numSamples > 0)
  163. {
  164. const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
  165. read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
  166. numSamples -= numToDo;
  167. startSampleInFile += numToDo;
  168. for (int j = numChannels; --j >= 0;)
  169. {
  170. int bufMax = INT_MIN;
  171. int bufMin = INT_MAX;
  172. const int* const b = tempBuffer[j];
  173. for (int i = 0; i < numToDo; ++i)
  174. {
  175. const int samp = b[i];
  176. if (samp < bufMin)
  177. bufMin = samp;
  178. if (samp > bufMax)
  179. bufMax = samp;
  180. }
  181. if (j == 0)
  182. {
  183. lmax = jmax (lmax, bufMax);
  184. lmin = jmin (lmin, bufMin);
  185. }
  186. else
  187. {
  188. rmax = jmax (rmax, bufMax);
  189. rmin = jmin (rmin, bufMin);
  190. }
  191. }
  192. }
  193. if (numChannels <= 1)
  194. {
  195. rmax = lmax;
  196. rmin = lmin;
  197. }
  198. lowestLeft = lmin / (float)INT_MAX;
  199. highestLeft = lmax / (float)INT_MAX;
  200. lowestRight = rmin / (float)INT_MAX;
  201. highestRight = rmax / (float)INT_MAX;
  202. }
  203. }
  204. int64 AudioFormatReader::searchForLevel (int64 startSample,
  205. int64 numSamplesToSearch,
  206. const double magnitudeRangeMinimum,
  207. const double magnitudeRangeMaximum,
  208. const int minimumConsecutiveSamples)
  209. {
  210. if (numSamplesToSearch == 0)
  211. return -1;
  212. const int bufferSize = 4096;
  213. MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
  214. int* tempBuffer[3];
  215. tempBuffer[0] = (int*) tempSpace.getData();
  216. tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
  217. tempBuffer[2] = 0;
  218. int consecutive = 0;
  219. int64 firstMatchPos = -1;
  220. jassert (magnitudeRangeMaximum > magnitudeRangeMinimum);
  221. const double doubleMin = jlimit (0.0, (double) INT_MAX, magnitudeRangeMinimum * INT_MAX);
  222. const double doubleMax = jlimit (doubleMin, (double) INT_MAX, magnitudeRangeMaximum * INT_MAX);
  223. const int intMagnitudeRangeMinimum = roundDoubleToInt (doubleMin);
  224. const int intMagnitudeRangeMaximum = roundDoubleToInt (doubleMax);
  225. while (numSamplesToSearch != 0)
  226. {
  227. const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize);
  228. int64 bufferStart = startSample;
  229. if (numSamplesToSearch < 0)
  230. bufferStart -= numThisTime;
  231. if (bufferStart >= (int) lengthInSamples)
  232. break;
  233. read ((int**) tempBuffer, 2, bufferStart, numThisTime, false);
  234. int num = numThisTime;
  235. while (--num >= 0)
  236. {
  237. if (numSamplesToSearch < 0)
  238. --startSample;
  239. bool matches = false;
  240. const int index = (int) (startSample - bufferStart);
  241. if (usesFloatingPointData)
  242. {
  243. const float sample1 = fabsf (((float*) tempBuffer[0]) [index]);
  244. if (sample1 >= magnitudeRangeMinimum
  245. && sample1 <= magnitudeRangeMaximum)
  246. {
  247. matches = true;
  248. }
  249. else if (numChannels > 1)
  250. {
  251. const float sample2 = fabsf (((float*) tempBuffer[1]) [index]);
  252. matches = (sample2 >= magnitudeRangeMinimum
  253. && sample2 <= magnitudeRangeMaximum);
  254. }
  255. }
  256. else
  257. {
  258. const int sample1 = abs (tempBuffer[0] [index]);
  259. if (sample1 >= intMagnitudeRangeMinimum
  260. && sample1 <= intMagnitudeRangeMaximum)
  261. {
  262. matches = true;
  263. }
  264. else if (numChannels > 1)
  265. {
  266. const int sample2 = abs (tempBuffer[1][index]);
  267. matches = (sample2 >= intMagnitudeRangeMinimum
  268. && sample2 <= intMagnitudeRangeMaximum);
  269. }
  270. }
  271. if (matches)
  272. {
  273. if (firstMatchPos < 0)
  274. firstMatchPos = startSample;
  275. if (++consecutive >= minimumConsecutiveSamples)
  276. {
  277. if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples)
  278. return -1;
  279. return firstMatchPos;
  280. }
  281. }
  282. else
  283. {
  284. consecutive = 0;
  285. firstMatchPos = -1;
  286. }
  287. if (numSamplesToSearch > 0)
  288. ++startSample;
  289. }
  290. if (numSamplesToSearch > 0)
  291. numSamplesToSearch -= numThisTime;
  292. else
  293. numSamplesToSearch += numThisTime;
  294. }
  295. return -1;
  296. }
  297. //==============================================================================
  298. AudioFormatWriter::AudioFormatWriter (OutputStream* const out,
  299. const String& formatName_,
  300. const double rate,
  301. const unsigned int numChannels_,
  302. const unsigned int bitsPerSample_)
  303. : sampleRate (rate),
  304. numChannels (numChannels_),
  305. bitsPerSample (bitsPerSample_),
  306. usesFloatingPointData (false),
  307. output (out),
  308. formatName (formatName_)
  309. {
  310. }
  311. AudioFormatWriter::~AudioFormatWriter()
  312. {
  313. delete output;
  314. }
  315. bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader,
  316. int64 startSample,
  317. int64 numSamplesToRead)
  318. {
  319. const int bufferSize = 16384;
  320. const int maxChans = 128;
  321. AudioSampleBuffer tempBuffer (reader.numChannels, bufferSize);
  322. int* buffers [maxChans];
  323. for (int i = maxChans; --i >= 0;)
  324. buffers[i] = 0;
  325. if (numSamplesToRead < 0)
  326. numSamplesToRead = reader.lengthInSamples;
  327. while (numSamplesToRead > 0)
  328. {
  329. const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
  330. for (int i = tempBuffer.getNumChannels(); --i >= 0;)
  331. buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
  332. if (! reader.read (buffers, maxChans, startSample, numToDo, false))
  333. return false;
  334. if (reader.usesFloatingPointData != isFloatingPoint())
  335. {
  336. int** bufferChan = buffers;
  337. while (*bufferChan != 0)
  338. {
  339. int* b = *bufferChan++;
  340. if (isFloatingPoint())
  341. {
  342. // int -> float
  343. const double factor = 1.0 / INT_MAX;
  344. for (int i = 0; i < numToDo; ++i)
  345. ((float*)b)[i] = (float) (factor * b[i]);
  346. }
  347. else
  348. {
  349. // float -> int
  350. for (int i = 0; i < numToDo; ++i)
  351. {
  352. const double samp = *(const float*) b;
  353. if (samp <= -1.0)
  354. *b++ = INT_MIN;
  355. else if (samp >= 1.0)
  356. *b++ = INT_MAX;
  357. else
  358. *b++ = roundDoubleToInt (INT_MAX * samp);
  359. }
  360. }
  361. }
  362. }
  363. if (! write ((const int**) buffers, numToDo))
  364. return false;
  365. numSamplesToRead -= numToDo;
  366. startSample += numToDo;
  367. }
  368. return true;
  369. }
  370. bool AudioFormatWriter::writeFromAudioSource (AudioSource& source,
  371. int numSamplesToRead,
  372. const int samplesPerBlock)
  373. {
  374. const int maxChans = 128;
  375. AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock);
  376. int* buffers [maxChans];
  377. while (numSamplesToRead > 0)
  378. {
  379. const int numToDo = jmin (numSamplesToRead, samplesPerBlock);
  380. AudioSourceChannelInfo info;
  381. info.buffer = &tempBuffer;
  382. info.startSample = 0;
  383. info.numSamples = numToDo;
  384. info.clearActiveBufferRegion();
  385. source.getNextAudioBlock (info);
  386. int i;
  387. for (i = maxChans; --i >= 0;)
  388. buffers[i] = 0;
  389. for (i = tempBuffer.getNumChannels(); --i >= 0;)
  390. buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
  391. if (! isFloatingPoint())
  392. {
  393. int** bufferChan = buffers;
  394. while (*bufferChan != 0)
  395. {
  396. int* b = *bufferChan++;
  397. // float -> int
  398. for (int j = numToDo; --j >= 0;)
  399. {
  400. const double samp = *(const float*) b;
  401. if (samp <= -1.0)
  402. *b++ = INT_MIN;
  403. else if (samp >= 1.0)
  404. *b++ = INT_MAX;
  405. else
  406. *b++ = roundDoubleToInt (INT_MAX * samp);
  407. }
  408. }
  409. }
  410. if (! write ((const int**) buffers, numToDo))
  411. return false;
  412. numSamplesToRead -= numToDo;
  413. }
  414. return true;
  415. }
  416. //==============================================================================
  417. AudioFormat::AudioFormat (const String& name,
  418. const tchar** const extensions)
  419. : formatName (name),
  420. fileExtensions (extensions)
  421. {
  422. }
  423. AudioFormat::~AudioFormat()
  424. {
  425. }
  426. //==============================================================================
  427. const String& AudioFormat::getFormatName() const
  428. {
  429. return formatName;
  430. }
  431. const StringArray& AudioFormat::getFileExtensions() const
  432. {
  433. return fileExtensions;
  434. }
  435. bool AudioFormat::canHandleFile (const File& f)
  436. {
  437. for (int i = 0; i < fileExtensions.size(); ++i)
  438. if (f.hasFileExtension (fileExtensions[i]))
  439. return true;
  440. return false;
  441. }
  442. bool AudioFormat::isCompressed()
  443. {
  444. return false;
  445. }
  446. const StringArray AudioFormat::getQualityOptions()
  447. {
  448. return StringArray();
  449. }
  450. END_JUCE_NAMESPACE