LongSound.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. /* LongSound.cpp
  2. *
  3. * Copyright (C) 1992-2008,2010-2018 Paul Boersma, 2007 Erez Volk (for FLAC and MP3)
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. * pb 2002/05/28
  20. * pb 2002/07/16 GPL
  21. * pb 2003/09/12 changed 5 to Melder_NUMBER_OF_AUDIO_FILE_TYPES
  22. * pb 2004/05/14 support for reading 24-bit and 32-bit audio files
  23. * pb 2004/11/24 made buffer length settable
  24. * pb 2006/12/10 MelderInfo
  25. * pb 2006/12/13 support for IEEE float 32-bit audio files
  26. * pb 2007/01/01 compatible with stereo sounds
  27. * pb 2007/01/27 more compatible with stereo sounds
  28. * pb 2007/03/17 domain quantity
  29. * Erez Volk 2007/03 FLAC reading
  30. * Erez Volk 2007/05/14 FLAC writing
  31. * Erez Volk 2007/06/04 MP3 reading
  32. * pb 2007/12/05 prefs
  33. * pb 2008/01/19 double
  34. * pb 2010/01/10 MP3 precision warning
  35. * fb 2010/02/25 corrected a bug that could cause LongSound_playPart to crash with an assertion on error
  36. * pb 2010/11/07 no longer do an assertion on thy resampledBuffer
  37. * pb 2010/12/20 support for more than 2 channels
  38. * pb 2011/06/02 C++
  39. * pb 2011/07/05 C++
  40. * pb 2014/06/16 more support for more than 2 channels
  41. */
  42. #include "LongSound.h"
  43. #include "Preferences.h"
  44. #include "flac_FLAC_stream_decoder.h"
  45. #include "mp3.h"
  46. Thing_implement (LongSound, Sampled, 0);
  47. Thing_implement (SoundAndLongSoundList, Ordered, 0);
  48. #define MARGIN 0.01
  49. #define USE_MEMMOVE 1
  50. constexpr integer minimumBufferDuration = 10; // seconds
  51. constexpr integer defaultBufferDuration = 60; // seconds
  52. constexpr integer maximumBufferDuration = 10000; // seconds
  53. static integer prefs_bufferLength;
  54. void LongSound_preferences () {
  55. Preferences_addInteger (U"LongSound.bufferLength", & prefs_bufferLength, defaultBufferDuration);
  56. }
  57. integer LongSound_getBufferSizePref_seconds () {
  58. return prefs_bufferLength;
  59. }
  60. void LongSound_setBufferSizePref_seconds (integer size) {
  61. prefs_bufferLength =
  62. size < minimumBufferDuration ? minimumBufferDuration : size > maximumBufferDuration ? maximumBufferDuration: size;
  63. }
  64. void structLongSound :: v_destroy () noexcept {
  65. /*
  66. * The play callback may contain a pointer to my buffer.
  67. * That pointer is about to dangle, so kill the playback.
  68. */
  69. MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
  70. if (mp3f)
  71. mp3f_delete (mp3f);
  72. if (flacDecoder) {
  73. FLAC__stream_decoder_finish (flacDecoder); // closes f
  74. FLAC__stream_decoder_delete (flacDecoder);
  75. } else if (f) {
  76. fclose (f);
  77. }
  78. NUMvector_free <int16> (buffer, 0);
  79. LongSound_Parent :: v_destroy ();
  80. }
  81. void structLongSound :: v_info () {
  82. static const conststring32 encodingStrings [1+20] = { U"none",
  83. U"linear 8 bit signed", U"linear 8 bit unsigned",
  84. U"linear 16 bit big-endian", U"linear 16 bit little-endian",
  85. U"linear 24 bit big-endian", U"linear 24 bit little-endian",
  86. U"linear 32 bit big-endian", U"linear 32 bit little-endian",
  87. U"mu-law", U"A-law", U"shorten", U"polyphone",
  88. U"IEEE float 32 bit big-endian", U"IEEE float 32 bit little-endian",
  89. U"FLAC", U"FLAC", U"FLAC", U"MP3", U"MP3", U"MP3" };
  90. structDaata :: v_info ();
  91. MelderInfo_writeLine (U"Duration: ", xmax - xmin, U" seconds");
  92. MelderInfo_writeLine (U"File name: ", Melder_fileToPath (& file));
  93. MelderInfo_writeLine (U"File type: ", audioFileType > Melder_NUMBER_OF_AUDIO_FILE_TYPES ? U"unknown" : Melder_audioFileTypeString (audioFileType));
  94. MelderInfo_writeLine (U"Number of channels: ", numberOfChannels);
  95. MelderInfo_writeLine (U"Encoding: ", encoding > 20 ? U"unknown" : encodingStrings [encoding]);
  96. MelderInfo_writeLine (U"Sampling frequency: ", sampleRate, U" Hz");
  97. MelderInfo_writeLine (U"Size: ", nx, U" samples");
  98. MelderInfo_writeLine (U"Start of sample data: ", startOfData, U" bytes from the start of the file");
  99. }
  100. static void _LongSound_FLAC_convertFloats (LongSound me, const int32 * const samples[], integer bitsPerSample, integer numberOfSamples) {
  101. double multiplier;
  102. switch (bitsPerSample) {
  103. case 8: multiplier = (1.0 / 128.0); break;
  104. case 16: multiplier = (1.0 / 32768.0); break;
  105. case 24: multiplier = (1.0 / 8388608.0); break;
  106. case 32: multiplier = (1.0 / 32768.0 / 65536.0); break;
  107. default: multiplier = 0.0;
  108. }
  109. for (integer i = 0; i < 2; ++i) {
  110. const int32 *input = samples [i];
  111. double *output = my compressedFloats [i];
  112. if (! output ) continue;
  113. for (integer j = 0; j < numberOfSamples; ++j)
  114. output [j] = (double) input [j] * multiplier;
  115. my compressedFloats [i] += numberOfSamples;
  116. }
  117. }
  118. static void _LongSound_FLAC_convertShorts (LongSound me, const int32 * const samples[], integer bitsPerSample, integer numberOfSamples) {
  119. for (integer channel = 0; channel < my numberOfChannels; ++ channel) {
  120. int16 *output = my compressedShorts + channel;
  121. const int32 *input = samples [channel];
  122. for (integer j = 0; j < numberOfSamples; ++ j, output += my numberOfChannels) {
  123. int32 sample = * (input ++);
  124. switch (bitsPerSample) {
  125. case 8: sample *= 256; break;
  126. case 16: break;
  127. case 24: sample /= 256; break;
  128. case 32: sample /= 65536; break;
  129. default: sample = 0; break;
  130. }
  131. *output = (int16) sample;
  132. }
  133. }
  134. my compressedShorts += numberOfSamples * my numberOfChannels;
  135. }
  136. static FLAC__StreamDecoderWriteStatus _LongSound_FLAC_write (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *void_me) {
  137. iam (LongSound);
  138. const FLAC__FrameHeader *header = & frame -> header;
  139. integer numberOfSamples = header -> blocksize;
  140. integer bitsPerSample = header -> bits_per_sample;
  141. (void) decoder;
  142. if (numberOfSamples > my compressedSamplesLeft)
  143. numberOfSamples = my compressedSamplesLeft;
  144. if (numberOfSamples == 0)
  145. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  146. if (my compressedMode == COMPRESSED_MODE_READ_FLOAT)
  147. _LongSound_FLAC_convertFloats (me, buffer, bitsPerSample, numberOfSamples);
  148. else
  149. _LongSound_FLAC_convertShorts (me, buffer, bitsPerSample, numberOfSamples);
  150. my compressedSamplesLeft -= numberOfSamples;
  151. return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
  152. }
  153. static void _LongSound_FLAC_error (const FLAC__StreamDecoder * /* decoder */, FLAC__StreamDecoderErrorStatus /* status */, void * /* longSound */) {
  154. }
  155. static void _LongSound_MP3_convertFloats (LongSound me, const MP3F_SAMPLE *channels [MP3F_MAX_CHANNELS], integer numberOfSamples) {
  156. for (integer i = 0; i < 2; ++i) {
  157. const MP3F_SAMPLE *input = channels [i];
  158. double *output = my compressedFloats [i];
  159. if (! output ) continue;
  160. for (integer j = 0; j < numberOfSamples; ++j)
  161. output [j] = mp3f_sample_to_float (input [j]);
  162. my compressedFloats [i] += numberOfSamples;
  163. }
  164. }
  165. static void _LongSound_MP3_convertShorts (LongSound me, const MP3F_SAMPLE *channels [MP3F_MAX_CHANNELS], integer numberOfSamples) {
  166. for (integer i = 0; i < my numberOfChannels; ++ i) {
  167. const MP3F_SAMPLE *input = channels [i];
  168. int16 *output = my compressedShorts + i;
  169. for (integer j = 0; j < numberOfSamples; ++j, output += my numberOfChannels) {
  170. int sample = *input++;
  171. *output = mp3f_sample_to_short (sample);
  172. }
  173. }
  174. my compressedShorts += numberOfSamples * my numberOfChannels;
  175. }
  176. static void _LongSound_MP3_convert (const MP3F_SAMPLE *channels [MP3F_MAX_CHANNELS], integer numberOfSamples, void *void_me) {
  177. iam (LongSound);
  178. if (numberOfSamples > my compressedSamplesLeft)
  179. numberOfSamples = my compressedSamplesLeft;
  180. if (numberOfSamples == 0)
  181. return;
  182. if (my compressedMode == COMPRESSED_MODE_READ_FLOAT)
  183. _LongSound_MP3_convertFloats (me, channels, numberOfSamples);
  184. else
  185. _LongSound_MP3_convertShorts (me, channels, numberOfSamples);
  186. my compressedSamplesLeft -= numberOfSamples;
  187. }
  188. static void LongSound_init (LongSound me, MelderFile file) {
  189. MelderFile_copy (file, & my file);
  190. MelderFile_open (file); // BUG: should be auto, but that requires an implemented .transfer()
  191. my f = file -> filePointer;
  192. my audioFileType = MelderFile_checkSoundFile (file, & my numberOfChannels, & my encoding, & my sampleRate, & my startOfData, & my nx);
  193. if (my audioFileType == 0)
  194. Melder_throw (U"File not recognized (LongSound only supports AIFF, AIFC, WAV, NeXT/Sun, NIST and FLAC).");
  195. if (my encoding == Melder_SHORTEN || my encoding == Melder_POLYPHONE)
  196. Melder_throw (U"LongSound does not support sound files compressed with \"shorten\".");
  197. if (my nx < 1)
  198. Melder_throw (U"Audio file contains 0 samples.");
  199. my xmin = 0.0;
  200. my dx = 1 / my sampleRate;
  201. my xmax = my nx * my dx;
  202. my x1 = 0.5 * my dx;
  203. my numberOfBytesPerSamplePoint = Melder_bytesPerSamplePoint (my encoding);
  204. my bufferLength = prefs_bufferLength;
  205. for (;;) {
  206. my nmax = my bufferLength * my numberOfChannels * my sampleRate * (1 + 3 * MARGIN);
  207. try {
  208. my buffer = NUMvector <int16> (0, my nmax * my numberOfChannels);
  209. break;
  210. } catch (MelderError) {
  211. my bufferLength *= 0.5; // try 30, 15, or 7.5 seconds
  212. if (my bufferLength < 5.0) // too short to be good
  213. throw;
  214. Melder_clearError (); // delete out-of-memory message
  215. }
  216. }
  217. my imin = 1;
  218. my imax = 0;
  219. my flacDecoder = nullptr;
  220. if (my audioFileType == Melder_FLAC) {
  221. my flacDecoder = FLAC__stream_decoder_new ();
  222. FLAC__stream_decoder_init_FILE (my flacDecoder, my f, _LongSound_FLAC_write, nullptr, _LongSound_FLAC_error, me);
  223. }
  224. my mp3f = nullptr;
  225. if (my audioFileType == Melder_MP3) {
  226. my mp3f = mp3f_new ();
  227. mp3f_set_file (my mp3f, my f);
  228. mp3f_set_callback (my mp3f, _LongSound_MP3_convert, me);
  229. if (! mp3f_analyze (my mp3f))
  230. Melder_throw (U"Unable to analyze MP3 file.");
  231. Melder_warning (U"Time measurements in MP3 files can be off by several tens of milliseconds. "
  232. U"Please convert to WAV file if you need time precision or annotation.");
  233. }
  234. }
  235. void structLongSound :: v_copy (Daata thee_Daata) {
  236. LongSound thee = static_cast <LongSound> (thee_Daata);
  237. thy f = nullptr;
  238. thy buffer = nullptr;
  239. LongSound_init (thee, & file);
  240. }
  241. autoLongSound LongSound_open (MelderFile file) {
  242. try {
  243. autoLongSound me = Thing_new (LongSound);
  244. LongSound_init (me.get(), file);
  245. return me;
  246. } catch (MelderError) {
  247. Melder_throw (U"LongSound not created.");
  248. }
  249. }
  250. static void _LongSound_FLAC_process (LongSound me, integer firstSample, integer numberOfSamples) {
  251. my compressedSamplesLeft = numberOfSamples - 1;
  252. if (! FLAC__stream_decoder_seek_absolute (my flacDecoder, firstSample))
  253. Melder_throw (U"Cannot seek in FLAC file ", & my file, U".");
  254. while (my compressedSamplesLeft > 0) {
  255. if (FLAC__stream_decoder_get_state (my flacDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
  256. Melder_throw (U"FLAC file ", & my file, U" too short.");
  257. if (! FLAC__stream_decoder_process_single (my flacDecoder))
  258. Melder_throw (U"Error decoding FLAC file ", & my file, U".");
  259. }
  260. }
  261. static void _LongSound_FILE_seekSample (LongSound me, integer firstSample) {
  262. if (fseek (my f, my startOfData + (firstSample - 1) * my numberOfChannels * my numberOfBytesPerSamplePoint, SEEK_SET))
  263. Melder_throw (U"Cannot seek in file ", & my file, U".");
  264. }
  265. static void _LongSound_FLAC_readAudioToShort (LongSound me, int16 *buffer, integer firstSample, integer numberOfSamples) {
  266. my compressedMode = COMPRESSED_MODE_READ_SHORT;
  267. my compressedShorts = buffer + 1;
  268. _LongSound_FLAC_process (me, firstSample, numberOfSamples);
  269. }
  270. static void _LongSound_MP3_process (LongSound me, integer firstSample, integer numberOfSamples) {
  271. if (! mp3f_seek (my mp3f, firstSample))
  272. Melder_throw (U"Cannot seek in MP3 file ", & my file, U".");
  273. my compressedSamplesLeft = numberOfSamples;
  274. if (! mp3f_read (my mp3f, numberOfSamples))
  275. Melder_throw (U"Error decoding MP3 file ", & my file, U".");
  276. }
  277. static void _LongSound_MP3_readAudioToShort (LongSound me, int16 *buffer, integer firstSample, integer numberOfSamples) {
  278. my compressedMode = COMPRESSED_MODE_READ_SHORT;
  279. my compressedShorts = buffer + 1;
  280. _LongSound_MP3_process (me, firstSample, numberOfSamples - 1);
  281. }
  282. void LongSound_readAudioToFloat (LongSound me, MAT buffer, integer firstSample) {
  283. Melder_assert (buffer.nrow == my numberOfChannels);
  284. if (my encoding == Melder_FLAC_COMPRESSION_16) {
  285. my compressedMode = COMPRESSED_MODE_READ_FLOAT;
  286. for (int ichan = 1; ichan <= my numberOfChannels; ichan ++) {
  287. my compressedFloats [ichan - 1] = & buffer [ichan] [1];
  288. }
  289. _LongSound_FLAC_process (me, firstSample, buffer.ncol);
  290. } else if (my encoding == Melder_MPEG_COMPRESSION_16) {
  291. my compressedMode = COMPRESSED_MODE_READ_FLOAT;
  292. for (int ichan = 1; ichan <= my numberOfChannels; ichan ++) {
  293. my compressedFloats [ichan - 1] = & buffer [ichan] [1];
  294. }
  295. _LongSound_MP3_process (me, firstSample, buffer.ncol);
  296. } else {
  297. _LongSound_FILE_seekSample (me, firstSample);
  298. Melder_readAudioToFloat (my f, my encoding, buffer);
  299. }
  300. }
  301. void LongSound_readAudioToShort (LongSound me, int16 *buffer, integer firstSample, integer numberOfSamples) {
  302. if (my encoding == Melder_FLAC_COMPRESSION_16) {
  303. _LongSound_FLAC_readAudioToShort (me, buffer, firstSample, numberOfSamples);
  304. } else if (my encoding == Melder_MPEG_COMPRESSION_16) {
  305. _LongSound_MP3_readAudioToShort (me, buffer, firstSample, numberOfSamples);
  306. } else {
  307. _LongSound_FILE_seekSample (me, firstSample);
  308. Melder_readAudioToShort (my f, my numberOfChannels, my encoding, buffer, numberOfSamples);
  309. }
  310. }
  311. autoSound LongSound_extractPart (LongSound me, double tmin, double tmax, bool preserveTimes) {
  312. try {
  313. if (tmax <= tmin) {
  314. tmin = my xmin;
  315. tmax = my xmax;
  316. }
  317. if (tmin < my xmin)
  318. tmin = my xmin;
  319. if (tmax > my xmax)
  320. tmax = my xmax;
  321. integer firstSample, lastSample;
  322. integer numberOfSamples = Sampled_getWindowSamples (me, tmin, tmax, & firstSample, & lastSample);
  323. if (numberOfSamples < 1)
  324. Melder_throw (U"Less than 1 sample in window.");
  325. autoSound thee = Sound_create (my numberOfChannels,
  326. tmin, tmax, numberOfSamples, my dx, Sampled_indexToX (me, firstSample));
  327. if (! preserveTimes) {
  328. thy xmin = 0.0;
  329. thy xmax -= tmin;
  330. thy x1 -= tmin;
  331. }
  332. LongSound_readAudioToFloat (me, thy z.get(), firstSample);
  333. return thee;
  334. } catch (MelderError) {
  335. Melder_throw (me, U": Sound not extracted.");
  336. }
  337. }
  338. static void _LongSound_readSamples (LongSound me, int16 *buffer, integer imin, integer imax) {
  339. LongSound_readAudioToShort (me, buffer, imin, imax - imin + 1);
  340. }
  341. static void writePartToOpenFile (LongSound me, int audioFileType, integer imin, integer n, MelderFile file, int numberOfChannels_override, int numberOfBitsPerSamplePoint) {
  342. integer ibuffer, offset, numberOfBuffers, numberOfSamplesInLastBuffer;
  343. offset = imin;
  344. numberOfBuffers = (n - 1) / my nmax + 1;
  345. numberOfSamplesInLastBuffer = (n - 1) % my nmax + 1;
  346. if (file -> filePointer) for (ibuffer = 1; ibuffer <= numberOfBuffers; ibuffer ++) {
  347. integer numberOfSamplesToCopy = ibuffer < numberOfBuffers ? my nmax : numberOfSamplesInLastBuffer;
  348. LongSound_readAudioToShort (me, my buffer, offset, numberOfSamplesToCopy);
  349. offset += numberOfSamplesToCopy;
  350. MelderFile_writeShortToAudio (file, numberOfChannels_override ? numberOfChannels_override : my numberOfChannels, Melder_defaultAudioFileEncoding (audioFileType, numberOfBitsPerSamplePoint), my buffer, numberOfSamplesToCopy);
  351. }
  352. /*
  353. * We "have" no samples any longer.
  354. */
  355. my imin = 1;
  356. my imax = 0;
  357. }
  358. void LongSound_savePartAsAudioFile (LongSound me, int audioFileType, double tmin, double tmax, MelderFile file, int numberOfBitsPerSamplePoint) {
  359. try {
  360. if (tmax <= tmin) {
  361. tmin = my xmin;
  362. tmax = my xmax;
  363. }
  364. if (tmin < my xmin)
  365. tmin = my xmin;
  366. if (tmax > my xmax)
  367. tmax = my xmax;
  368. integer imin, imax;
  369. integer n = Sampled_getWindowSamples (me, tmin, tmax, & imin, & imax);
  370. if (n < 1) Melder_throw (U"Less than 1 sample selected.");
  371. autoMelderFile mfile = MelderFile_create (file);
  372. MelderFile_writeAudioFileHeader (file, audioFileType, my sampleRate, n, my numberOfChannels, numberOfBitsPerSamplePoint);
  373. writePartToOpenFile (me, audioFileType, imin, n, file, 0, numberOfBitsPerSamplePoint);
  374. MelderFile_writeAudioFileTrailer (file, audioFileType, my sampleRate, n, my numberOfChannels, numberOfBitsPerSamplePoint);
  375. mfile.close ();
  376. } catch (MelderError) {
  377. Melder_throw (me, U": not written to sound file ", file, U".");
  378. }
  379. }
  380. void LongSound_saveChannelAsAudioFile (LongSound me, int audioFileType, int channel, MelderFile file) {
  381. try {
  382. if (my numberOfChannels != 2)
  383. Melder_throw (U"This audio file is not a stereo file. It does not have a ", channel == 0 ? U"left" : U"right", U" channel.");
  384. autoMelderFile mfile = MelderFile_create (file);
  385. if (file -> filePointer) {
  386. MelderFile_writeAudioFileHeader (file, audioFileType, my sampleRate, my nx, 1, 8 * my numberOfBytesPerSamplePoint);
  387. }
  388. writePartToOpenFile (me, audioFileType, 1, my nx, file, channel == 0 ? -1 : -2, 8 * my numberOfBytesPerSamplePoint);
  389. MelderFile_writeAudioFileTrailer (file, audioFileType, my sampleRate, my nx, 1, 8 * my numberOfBytesPerSamplePoint);
  390. mfile.close ();
  391. } catch (MelderError) {
  392. Melder_throw (U"Channel ", channel, U" of ", me, U": not written to sound file ", file, U".");
  393. }
  394. }
  395. static void _LongSound_haveSamples (LongSound me, integer imin, integer imax) {
  396. integer n = imax - imin + 1;
  397. Melder_assert (n <= my nmax);
  398. /*
  399. * Included?
  400. */
  401. if (imin >= my imin && imax <= my imax)
  402. return;
  403. /*
  404. * Extendable?
  405. */
  406. if (imin >= my imin && imax - my imin + 1 <= my nmax) {
  407. _LongSound_readSamples (me, my buffer + (my imax - my imin + 1) * my numberOfChannels, my imax + 1, imax);
  408. my imax = imax;
  409. return;
  410. }
  411. /*
  412. * Determine the loadable imin..imax.
  413. * Add margins on both sides.
  414. */
  415. imin -= MARGIN * n;
  416. if (imin < 1) imin = 1;
  417. imax = imin + Melder_ifloor ((1.0 + 2.0 * MARGIN) * n);
  418. if (imax > my nx) imax = my nx;
  419. imin = imax - Melder_ifloor ((1.0 + 2.0 * MARGIN) * n);
  420. if (imin < 1) imin = 1;
  421. Melder_assert (imax - imin + 1 <= my nmax);
  422. /*
  423. * Overlap?
  424. */
  425. if (imax < my imin || imin > my imax) {
  426. /*
  427. * No overlap.
  428. */
  429. _LongSound_readSamples (me, my buffer, imin, imax);
  430. } else if (imin < my imin) {
  431. /*
  432. * Left overlap.
  433. */
  434. if (imax <= my imax) {
  435. /*
  436. * Only left overlap (e.g. scrolling up).
  437. */
  438. integer nshift = (imax - my imin + 1) * my numberOfChannels, shift = (my imin - imin) * my numberOfChannels;
  439. #if USE_MEMMOVE
  440. memmove (my buffer + shift, my buffer, nshift * sizeof (int16));
  441. #else
  442. for (i = nshift - 1; i >= 0; i --)
  443. my buffer [i + shift] = my buffer [i];
  444. #endif
  445. _LongSound_readSamples (me, my buffer, imin, my imin - 1);
  446. } else {
  447. /*
  448. * Left and right overlap (e.g. zooming out).
  449. */
  450. integer nshift = (my imax - my imin + 1) * my numberOfChannels, shift = (my imin - imin) * my numberOfChannels;
  451. #if USE_MEMMOVE
  452. memmove (my buffer + shift, my buffer, nshift * sizeof (int16));
  453. #else
  454. for (i = nshift - 1; i >= 0; i --)
  455. my buffer [i + shift] = my buffer [i];
  456. #endif
  457. _LongSound_readSamples (me, my buffer, imin, my imin - 1);
  458. _LongSound_readSamples (me, my buffer + (my imax - imin + 1) * my numberOfChannels, my imax + 1, imax);
  459. }
  460. } else {
  461. /*
  462. * Only right overlap (e.g. scrolling down).
  463. */
  464. integer nshift = (my imax - imin + 1) * my numberOfChannels, shift = (imin - my imin) * my numberOfChannels;
  465. #if USE_MEMMOVE
  466. memmove (my buffer, my buffer + shift, nshift * sizeof (int16));
  467. #else
  468. for (i = 0; i < nshift; i ++)
  469. my buffer [i] = my buffer [i + shift];
  470. #endif
  471. _LongSound_readSamples (me, my buffer + (my imax - imin + 1) * my numberOfChannels, my imax + 1, imax);
  472. }
  473. my imin = imin;
  474. my imax = imax;
  475. }
  476. bool LongSound_haveWindow (LongSound me, double tmin, double tmax) {
  477. integer imin, imax;
  478. integer n = Sampled_getWindowSamples (me, tmin, tmax, & imin, & imax);
  479. if ((1.0 + 2 * MARGIN) * n + 1 > my nmax) return false;
  480. _LongSound_haveSamples (me, imin, imax);
  481. return true;
  482. }
  483. void LongSound_getWindowExtrema (LongSound me, double tmin, double tmax, int channel, double *minimum, double *maximum) {
  484. integer imin, imax;
  485. (void) Sampled_getWindowSamples (me, tmin, tmax, & imin, & imax);
  486. *minimum = 1.0;
  487. *maximum = -1.0;
  488. try {
  489. LongSound_haveWindow (me, tmin, tmax);
  490. } catch (MelderError) {
  491. Melder_clearError ();
  492. return;
  493. }
  494. integer minimum_int = 32767, maximum_int = -32768;
  495. for (integer i = imin; i <= imax; i ++) {
  496. integer value = my buffer [(i - my imin) * my numberOfChannels + channel - 1];
  497. if (value < minimum_int) minimum_int = value;
  498. if (value > maximum_int) maximum_int = value;
  499. }
  500. *minimum = minimum_int / 32768.0;
  501. *maximum = maximum_int / 32768.0;
  502. }
  503. static struct LongSoundPlay {
  504. integer numberOfSamples, i1, i2, silenceBefore, silenceAfter;
  505. double tmin, tmax, dt, t1;
  506. int16 *resampledBuffer;
  507. Sound_PlayCallback callback;
  508. Thing boss;
  509. } thePlayingLongSound;
  510. static bool melderPlayCallback (void *closure, integer samplesPlayed) {
  511. struct LongSoundPlay *me = (struct LongSoundPlay *) closure;
  512. int phase = 2;
  513. double t = samplesPlayed <= my silenceBefore ? my tmin :
  514. samplesPlayed >= my silenceBefore + my numberOfSamples ? my tmax :
  515. my t1 + (my i1 - 1.5 + samplesPlayed - my silenceBefore) * my dt;
  516. if (! MelderAudio_isPlaying) {
  517. phase = 3;
  518. Melder_free (my resampledBuffer);
  519. }
  520. if (my callback)
  521. return my callback (my boss, phase, my tmin, my tmax, t);
  522. return true;
  523. }
  524. void LongSound_playPart (LongSound me, double tmin, double tmax,
  525. Sound_PlayCallback callback, Thing boss)
  526. {
  527. struct LongSoundPlay *thee = (struct LongSoundPlay *) & thePlayingLongSound;
  528. MelderAudio_stopPlaying (MelderAudio_IMPLICIT);
  529. Melder_free (thy resampledBuffer); // just in case, and after playing has stopped
  530. try {
  531. bool fits = LongSound_haveWindow (me, tmin, tmax);
  532. integer bestSampleRate = MelderAudio_getOutputBestSampleRate (my sampleRate), n, i1, i2;
  533. if (! fits)
  534. Melder_throw (U"Sound too long (", tmax - tmin, U" seconds).");
  535. /*
  536. * Assign to *thee only after stopping the playing sound.
  537. */
  538. thy tmin = tmin;
  539. thy tmax = tmax;
  540. thy callback = callback;
  541. thy boss = boss;
  542. if ((n = Sampled_getWindowSamples (me, tmin, tmax, & i1, & i2)) < 2) return;
  543. if (bestSampleRate == my sampleRate) {
  544. thy numberOfSamples = n;
  545. thy dt = 1 / my sampleRate;
  546. thy t1 = my x1;
  547. thy i1 = i1;
  548. thy i2 = i2;
  549. thy silenceBefore = Melder_iroundTowardsZero (my sampleRate * MelderAudio_getOutputSilenceBefore ());
  550. thy silenceAfter = Melder_iroundTowardsZero (my sampleRate * MelderAudio_getOutputSilenceAfter ());
  551. if (thy callback)
  552. thy callback (thy boss, 1, tmin, tmax, tmin);
  553. if (thy silenceBefore > 0 || thy silenceAfter > 0 || 1) {
  554. thy resampledBuffer = Melder_calloc (int16, (thy silenceBefore + thy numberOfSamples + thy silenceAfter) * my numberOfChannels);
  555. memcpy (& thy resampledBuffer [thy silenceBefore * my numberOfChannels], & my buffer [(i1 - my imin) * my numberOfChannels],
  556. thy numberOfSamples * sizeof (int16) * my numberOfChannels);
  557. MelderAudio_play16 (thy resampledBuffer, my sampleRate, thy silenceBefore + thy numberOfSamples + thy silenceAfter,
  558. my numberOfChannels, melderPlayCallback, thee);
  559. } else {
  560. MelderAudio_play16 (my buffer + (i1 - my imin) * my numberOfChannels, my sampleRate,
  561. thy numberOfSamples, my numberOfChannels, melderPlayCallback, thee);
  562. }
  563. } else {
  564. integer newSampleRate = bestSampleRate;
  565. integer newN = ((double) n * newSampleRate) / my sampleRate - 1;
  566. integer silenceBefore = Melder_iroundTowardsZero (newSampleRate * MelderAudio_getOutputSilenceBefore ());
  567. integer silenceAfter = Melder_iroundTowardsZero (newSampleRate * MelderAudio_getOutputSilenceAfter ());
  568. int16 *resampledBuffer = Melder_calloc (int16, (silenceBefore + newN + silenceAfter) * my numberOfChannels);
  569. int16 *from = my buffer + (i1 - my imin) * my numberOfChannels; // guaranteed: from [0 .. (my imax - my imin + 1) * nchan]
  570. double t1 = my x1, dt = 1.0 / newSampleRate;
  571. thy numberOfSamples = newN;
  572. thy dt = dt;
  573. thy t1 = t1 + i1 / my sampleRate;
  574. thy i1 = 0;
  575. thy i2 = newN - 1;
  576. thy silenceBefore = silenceBefore;
  577. thy silenceAfter = silenceAfter;
  578. thy resampledBuffer = resampledBuffer;
  579. if (my numberOfChannels == 1) {
  580. for (integer i = 0; i < newN; i ++) {
  581. double t = t1 + i * dt; // from t1 to t1 + (newN-1) * dt
  582. double index = (t - t1) * my sampleRate; // from 0
  583. integer flore = Melder_iroundTowardsZero (index);
  584. double fraction = index - flore;
  585. resampledBuffer [i + silenceBefore] = (1.0 - fraction) * from [flore] + fraction * from [flore + 1];
  586. }
  587. } else if (my numberOfChannels == 2) {
  588. for (integer i = 0; i < newN; i ++) {
  589. double t = t1 + i * dt;
  590. double index = (t - t1) * my sampleRate;
  591. integer flore = Melder_iroundTowardsZero (index);
  592. double fraction = index - flore;
  593. integer ii = i + silenceBefore;
  594. resampledBuffer [ii + ii] = (1.0 - fraction) * from [flore + flore] + fraction * from [flore + flore + 2];
  595. resampledBuffer [ii + ii + 1] = (1.0 - fraction) * from [flore + flore + 1] + fraction * from [flore + flore + 3];
  596. }
  597. } else {
  598. for (integer i = 0; i < newN; i ++) {
  599. double t = t1 + i * dt;
  600. double index = (t - t1) * my sampleRate;
  601. integer flore = Melder_iroundTowardsZero (index);
  602. double fraction = index - flore;
  603. integer ii = (i + silenceBefore) * my numberOfChannels;
  604. for (integer chan = 0; chan < my numberOfChannels; chan ++) {
  605. resampledBuffer [ii + chan] =
  606. (1.0 - fraction) * from [flore * my numberOfChannels + chan] +
  607. fraction * from [(flore + 1) * my numberOfChannels + chan];
  608. }
  609. }
  610. }
  611. if (thy callback)
  612. thy callback (thy boss, 1, tmin, tmax, tmin);
  613. MelderAudio_play16 (resampledBuffer, newSampleRate, silenceBefore + newN + silenceAfter, my numberOfChannels, melderPlayCallback, thee);
  614. }
  615. //Melder_free (thy resampledBuffer); // cannot do that, because MelderAudio_play16 isn't necessarily synchronous
  616. } catch (MelderError) {
  617. Melder_free (thy resampledBuffer);
  618. Melder_throw (me, U": not played.");
  619. }
  620. }
  621. void LongSound_concatenate (SoundAndLongSoundList me, MelderFile file, int audioFileType, int numberOfBitsPerSamplePoint) {
  622. try {
  623. integer sampleRate, n; /* Integer sampling frequencies only, because of possible rounding errors. */
  624. integer numberOfChannels;
  625. if (my size < 1)
  626. Melder_throw (U"No Sound or LongSound objects to concatenate.");
  627. /*
  628. * The sampling frequencies and numbers of channels must be equal for all (long)sounds.
  629. */
  630. Sampled data = my at [1];
  631. if (data -> classInfo == classSound) {
  632. Sound sound = (Sound) data;
  633. sampleRate = Melder_iround (1.0 / sound -> dx);
  634. numberOfChannels = sound -> ny;
  635. n = sound -> nx;
  636. } else {
  637. LongSound longSound = (LongSound) data;
  638. sampleRate = Melder_iroundTowardsZero (longSound -> sampleRate);
  639. numberOfChannels = longSound -> numberOfChannels;
  640. n = longSound -> nx;
  641. }
  642. /*
  643. * Check whether all the sampling frequencies and channels match.
  644. */
  645. for (integer i = 2; i <= my size; i ++) {
  646. bool sampleRatesMatch, numbersOfChannelsMatch;
  647. data = my at [i];
  648. if (data -> classInfo == classSound) {
  649. Sound sound = (Sound) data;
  650. sampleRatesMatch = ( Melder_iround (1.0 / sound -> dx) == sampleRate );
  651. numbersOfChannelsMatch = sound -> ny == numberOfChannels;
  652. n += sound -> nx;
  653. } else {
  654. LongSound longSound = (LongSound) data;
  655. sampleRatesMatch = ( longSound -> sampleRate == sampleRate );
  656. numbersOfChannelsMatch = longSound -> numberOfChannels == numberOfChannels;
  657. n += longSound -> nx;
  658. }
  659. if (! sampleRatesMatch)
  660. Melder_throw (U"Sampling frequencies are not equal.");
  661. if (! numbersOfChannelsMatch)
  662. Melder_throw (U"Cannot mix stereo and mono.");
  663. }
  664. /*
  665. * Create output file and write header.
  666. */
  667. autoMelderFile mfile = MelderFile_create (file);
  668. if (file -> filePointer)
  669. MelderFile_writeAudioFileHeader (file, audioFileType, sampleRate, n, numberOfChannels, numberOfBitsPerSamplePoint);
  670. for (integer i = 1; i <= my size; i ++) {
  671. data = my at [i];
  672. if (data -> classInfo == classSound) {
  673. Sound sound = (Sound) data;
  674. if (file -> filePointer) {
  675. MelderFile_writeFloatToAudio (file, sound -> z.get(),
  676. Melder_defaultAudioFileEncoding (audioFileType, numberOfBitsPerSamplePoint), true);
  677. }
  678. } else {
  679. LongSound longSound = (LongSound) data;
  680. writePartToOpenFile (longSound, audioFileType, 1, longSound -> nx, file, 0, numberOfBitsPerSamplePoint);
  681. }
  682. }
  683. MelderFile_writeAudioFileTrailer (file, audioFileType, sampleRate, n, numberOfChannels, numberOfBitsPerSamplePoint);
  684. mfile.close ();
  685. } catch (MelderError) {
  686. Melder_throw (U"Sounds not concatenated and not saved to ", file, U".");
  687. }
  688. }
  689. /* End of file LongSound.cpp */