Sound.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  1. /* Sound.cpp
  2. *
  3. * Copyright (C) 1992-2018 Paul Boersma
  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. * a selection of changes:
  20. * pb 2006/12/31 stereo
  21. * pb 2010/03/26 Sounds_convolve, Sounds_crossCorrelate, Sound_autocorrelate
  22. */
  23. #include "Sound.h"
  24. #include "Sound_extensions.h"
  25. #include "NUM2.h"
  26. #include "enums_getText.h"
  27. #include "Sound_enums.h"
  28. #include "enums_getValue.h"
  29. #include "Sound_enums.h"
  30. Thing_implement (Sound, Vector, 2);
  31. autoSound Sound_clipboard;
  32. void structSound :: v_info () {
  33. structDaata :: v_info ();
  34. MelderInfo_writeLine (U"Number of channels: ", our ny, our ny == 1 ? U" (mono)" : our ny == 2 ? U" (stereo)" : U"");
  35. MelderInfo_writeLine (U"Time domain:");
  36. MelderInfo_writeLine (U" Start time: ", our xmin, U" seconds");
  37. MelderInfo_writeLine (U" End time: ", our xmax, U" seconds");
  38. MelderInfo_writeLine (U" Total duration: ", our xmax - our xmin, U" seconds");
  39. MelderInfo_writeLine (U"Time sampling:");
  40. MelderInfo_writeLine (U" Number of samples: ", our nx);
  41. MelderInfo_writeLine (U" Sampling period: ", our dx, U" seconds");
  42. MelderInfo_writeLine (U" Sampling frequency: ", Melder_single (1.0 / our dx), U" Hz");
  43. MelderInfo_writeLine (U" First sample centred at: ", our x1, U" seconds");
  44. integer numberOfCells = our nx * our ny;
  45. bool thereAreEnoughObservationsToComputeFirstOrderOverallStatistics = ( numberOfCells >= 1 );
  46. if (thereAreEnoughObservationsToComputeFirstOrderOverallStatistics) {
  47. double minimum_Pa = our z [1] [1], maximum_Pa = minimum_Pa;
  48. longdouble sum_Pa = 0.0, sumOfSquares_Pa2 = 0.0;
  49. for (integer channel = 1; channel <= our ny; channel ++) {
  50. double *waveform_Pa = our z [channel];
  51. for (integer i = 1; i <= our nx; i ++) {
  52. double value_Pa = waveform_Pa [i];
  53. sum_Pa += value_Pa;
  54. sumOfSquares_Pa2 += value_Pa * value_Pa;
  55. if (value_Pa < minimum_Pa) minimum_Pa = value_Pa;
  56. if (value_Pa > maximum_Pa) maximum_Pa = value_Pa;
  57. }
  58. }
  59. MelderInfo_writeLine (U"Amplitude:");
  60. MelderInfo_writeLine (U" Minimum: ", Melder_single (minimum_Pa), U" Pascal");
  61. MelderInfo_writeLine (U" Maximum: ", Melder_single (maximum_Pa), U" Pascal");
  62. double mean_Pa = (double) sum_Pa / numberOfCells;
  63. MelderInfo_writeLine (U" Mean: ", Melder_single (mean_Pa), U" Pascal");
  64. double meanSquare_Pa2 = (double) sumOfSquares_Pa2 / numberOfCells;
  65. double rootMeanSquare_Pa = sqrt (meanSquare_Pa2);
  66. MelderInfo_writeLine (U" Root-mean-square: ", Melder_single (rootMeanSquare_Pa), U" Pascal");
  67. double energy_Pa2s = (double) sumOfSquares_Pa2 * our dx / our ny; // Pa2 s = kg2 m-2 s-3
  68. MelderInfo_write (U"Total energy: ", Melder_single (energy_Pa2s), U" Pascal\u00B2 sec");
  69. const double rho_c = 400.0; // rho = 1.14 kg m-3; c = 353 m s-1; [rho c] = kg m-2 s-1
  70. double energy_J_m2 = energy_Pa2s / rho_c; // kg s-2 = Joule m-2
  71. MelderInfo_writeLine (U" (energy in air: ", Melder_single (energy_J_m2), U" Joule/m\u00B2)");
  72. const double physicalDuration_s = our dx * our nx;
  73. double power_W_m2 = energy_J_m2 / physicalDuration_s; // kg s-3 = Watt/m2
  74. MelderInfo_write (U"Mean power (intensity) in air: ", Melder_single (power_W_m2), U" Watt/m\u00B2");
  75. if (power_W_m2 != 0.0) {
  76. const double referencePower_W_m2 = 1.0e-12; // this equals the square of 2.0e-5 Pa, divided by rho c
  77. double power_dB = 10.0 * log10 (power_W_m2 / referencePower_W_m2);
  78. MelderInfo_writeLine (U" = ", Melder_half (power_dB), U" dB");
  79. } else {
  80. MelderInfo_writeLine (U"");
  81. }
  82. }
  83. bool thereAreEnoughObservationsToComputeSecondOrderChannelStatistics = ( our nx >= 2 );
  84. if (thereAreEnoughObservationsToComputeSecondOrderChannelStatistics) {
  85. for (integer channel = 1; channel <= our ny; channel ++) {
  86. double stdev = NUMstdev (constVEC (our z [channel], our nx));
  87. MelderInfo_writeLine (U"Standard deviation in channel ", channel, U": ", Melder_single (stdev), U" Pascal");
  88. }
  89. }
  90. }
  91. double structSound :: v_getMatrix (integer irow, integer icol) {
  92. if (irow < 1 || irow > our ny) {
  93. if (irow == 0) {
  94. if (icol < 1 || icol > nx) return 0.0;
  95. if (our ny == 1) return our z [1] [icol]; // optimization
  96. if (our ny == 2) return 0.5 * (our z [1] [icol] + our z [2] [icol]); // optimization
  97. longdouble sum = 0.0;
  98. for (integer channel = 1; channel <= ny; channel ++) {
  99. sum += our z [channel] [icol];
  100. }
  101. return (double) sum / our ny;
  102. }
  103. return 0.0;
  104. }
  105. if (icol < 1 || icol > nx) return 0.0;
  106. return our z [irow] [icol];
  107. }
  108. double structSound :: v_getFunction2 (double x, double y) {
  109. integer channel = Melder_ifloor (y);
  110. if (channel < 0 || channel > our ny || y != (double) channel) return 0.0;
  111. return v_getFunction1 (channel, x);
  112. }
  113. autoSound Sound_create (integer numberOfChannels, double xmin, double xmax, integer nx, double dx, double x1) {
  114. try {
  115. autoSound me = Thing_new (Sound);
  116. Matrix_init (me.get(), xmin, xmax, nx, dx, x1, 1, numberOfChannels, numberOfChannels, 1, 1);
  117. return me;
  118. } catch (MelderError) {
  119. Melder_throw (U"Sound not created.");
  120. }
  121. }
  122. autoSound Sound_createSimple (integer numberOfChannels, double duration, double samplingFrequency) {
  123. Melder_assert (duration >= 0.0);
  124. Melder_assert (samplingFrequency > 0.0);
  125. double numberOfSamples_f = round (duration * samplingFrequency);
  126. if (numberOfSamples_f > (double) INT32_MAX)
  127. Melder_throw (U"Cannot create sounds with more than ", Melder_bigInteger (INT32_MAX), U" samples, because they cannot be saved to disk.");
  128. return Sound_create (numberOfChannels, 0.0, duration, (integer) (int32) numberOfSamples_f,
  129. 1.0 / samplingFrequency, 0.5 / samplingFrequency);
  130. }
  131. autoSound Sound_convertToMono (Sound me) {
  132. if (my ny == 1) return Data_copy (me); // optimization
  133. try {
  134. autoSound thee = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1);
  135. if (my ny == 2) { // optimization
  136. for (integer i = 1; i <= my nx; i ++) {
  137. thy z [1] [i] = 0.5 * (my z [1] [i] + my z [2] [i]);
  138. }
  139. } else {
  140. for (integer i = 1; i <= my nx; i ++) {
  141. double sum = my z [1] [i] + my z [2] [i] + my z [3] [i];
  142. for (integer channel = 4; channel <= my ny; channel ++) {
  143. sum += my z [channel] [i];
  144. }
  145. thy z [1] [i] = sum / my ny;
  146. }
  147. }
  148. return thee;
  149. } catch (MelderError) {
  150. Melder_throw (me, U": not converted to mono.");
  151. }
  152. }
  153. autoSound Sound_convertToStereo (Sound me) {
  154. if (my ny == 2) return Data_copy (me);
  155. try {
  156. if (my ny > 2) {
  157. Melder_throw (U"The Sound has ", my ny, U" channels; don't know which to choose.");
  158. }
  159. Melder_assert (my ny == 1);
  160. autoSound thee = Sound_create (2, my xmin, my xmax, my nx, my dx, my x1);
  161. for (integer i = 1; i <= my nx; i ++) {
  162. thy z [1] [i] = thy z [2] [i] = my z [1] [i];
  163. }
  164. return thee;
  165. } catch (MelderError) {
  166. Melder_throw (me, U": not converted to stereo.");
  167. }
  168. }
  169. autoSound Sounds_combineToStereo (OrderedOf<structSound>* me) {
  170. try {
  171. integer totalNumberOfChannels = 0;
  172. double sharedSamplingPeriod = 0.0;
  173. for (integer isound = 1; isound <= my size; isound ++) {
  174. Sound sound = my at [isound];
  175. totalNumberOfChannels += sound -> ny;
  176. if (sharedSamplingPeriod == 0.0) {
  177. sharedSamplingPeriod = sound -> dx;
  178. } else if (sound -> dx != sharedSamplingPeriod) {
  179. Melder_throw (U"To combine sounds, their sampling frequencies should be equal.\n"
  180. U"You could resample one or more of the sounds before combining.");
  181. }
  182. }
  183. Melder_assert (my size > 0);
  184. double sharedMinimumTime = my at [1] -> xmin;
  185. double sharedMaximumTime = my at [1] -> xmax;
  186. for (integer isound = 2; isound <= my size; isound ++) {
  187. Sound sound = my at [isound];
  188. if (sound -> xmin < sharedMinimumTime) sharedMinimumTime = sound -> xmin;
  189. if (sound -> xmax > sharedMaximumTime) sharedMaximumTime = sound -> xmax;
  190. }
  191. autoNUMvector <integer> numberOfInitialZeroes (1, my size);
  192. integer sharedNumberOfSamples = 0;
  193. double sumOfFirstTimes = 0.0;
  194. for (integer isound = 1; isound <= my size; isound ++) {
  195. Sound sound = my at [isound];
  196. numberOfInitialZeroes [isound] = Melder_ifloor ((sound -> xmin - sharedMinimumTime) / sharedSamplingPeriod);
  197. double newFirstTime = sound -> x1 - sound -> dx * numberOfInitialZeroes [isound];
  198. sumOfFirstTimes += newFirstTime;
  199. integer newNumberOfSamplesThroughLastNonzero = sound -> nx + numberOfInitialZeroes [isound];
  200. if (newNumberOfSamplesThroughLastNonzero > sharedNumberOfSamples) sharedNumberOfSamples = newNumberOfSamplesThroughLastNonzero;
  201. }
  202. double sharedTimeOfFirstSample = sumOfFirstTimes / my size; // this is an approximation
  203. autoSound thee = Sound_create (totalNumberOfChannels, sharedMinimumTime, sharedMaximumTime,
  204. sharedNumberOfSamples, sharedSamplingPeriod, sharedTimeOfFirstSample);
  205. integer channelNumber = 0;
  206. for (integer isound = 1; isound <= my size; isound ++) {
  207. Sound sound = my at [isound];
  208. integer offset = numberOfInitialZeroes [isound];
  209. for (integer ichan = 1; ichan <= sound -> ny; ichan ++) {
  210. channelNumber ++;
  211. for (integer isamp = 1; isamp <= sound -> nx; isamp ++) {
  212. thy z [channelNumber] [isamp + offset] = sound -> z [ichan] [isamp];
  213. }
  214. }
  215. }
  216. return thee;
  217. } catch (MelderError) {
  218. Melder_throw (U"Sounds not combined to stereo.");
  219. }
  220. }
  221. autoSound Sound_extractChannel (Sound me, integer ichan) {
  222. try {
  223. if (ichan <= 0 || ichan > my ny)
  224. Melder_throw (U"There is no channel ", ichan, U".");
  225. autoSound thee = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1);
  226. for (integer isamp = 1; isamp <= my nx; isamp ++) {
  227. thy z [1] [isamp] = my z [ichan] [isamp];
  228. }
  229. return thee;
  230. } catch (MelderError) {
  231. Melder_throw (me, U": channel ", ichan, U" not extracted.");
  232. }
  233. }
  234. autoSound Sound_extractChannels (Sound me, constVEC channelNumbers) {
  235. try {
  236. integer numberOfChannels = channelNumbers.size;
  237. Melder_require (numberOfChannels > 0,
  238. U"The number of channels should be greater than 0.");
  239. autoSound you = Sound_create (numberOfChannels, my xmin, my xmax, my nx, my dx, my x1);
  240. for (integer ichan = 1; ichan <= numberOfChannels; ichan ++) {
  241. integer originalChannelNumber = Melder_iround (channelNumbers [ichan]);
  242. Melder_require (originalChannelNumber > 0,
  243. U"Your channel number is ", originalChannelNumber,
  244. U", but it should be positive.");
  245. Melder_require (originalChannelNumber <= my ny,
  246. U"Your channel number is ", originalChannelNumber,
  247. U", but it should not be greater than my number of channels, which is ",
  248. my ny, U".");
  249. double *from = my z [originalChannelNumber], *to = your z [ichan];
  250. for (integer isamp = 1; isamp <= my nx; isamp ++) {
  251. to [isamp] = from [isamp];
  252. }
  253. }
  254. return you;
  255. } catch (MelderError) {
  256. Melder_throw (me, U": channels not extracted.");
  257. }
  258. }
  259. static double getSumOfSquares (Sound me, double xmin, double xmax, integer *n) {
  260. if (xmax <= xmin) { xmin = my xmin; xmax = my xmax; }
  261. integer imin, imax;
  262. *n = Sampled_getWindowSamples (me, xmin, xmax, & imin, & imax);
  263. if (*n < 1) return undefined;
  264. longdouble sum2 = 0.0;
  265. for (integer channel = 1; channel <= my ny; channel ++) {
  266. double *amplitude = my z [channel];
  267. for (integer i = imin; i <= imax; i ++) {
  268. double value = amplitude [i];
  269. sum2 += value * value;
  270. }
  271. }
  272. return (double) sum2;
  273. }
  274. double Sound_getRootMeanSquare (Sound me, double xmin, double xmax) {
  275. integer n;
  276. double sum2 = getSumOfSquares (me, xmin, xmax, & n);
  277. return isdefined (sum2) ? sqrt (sum2 / (n * my ny)) : undefined;
  278. }
  279. double Sound_getEnergy (Sound me, double xmin, double xmax) {
  280. integer n;
  281. double sum2 = getSumOfSquares (me, xmin, xmax, & n);
  282. return isdefined (sum2) ? sum2 * my dx / my ny : undefined;
  283. }
  284. double Sound_getPower (Sound me, double xmin, double xmax) {
  285. integer n;
  286. double sum2 = getSumOfSquares (me, xmin, xmax, & n);
  287. return isdefined (sum2) ? sum2 / (n * my ny) : undefined;
  288. }
  289. double Sound_getEnergyInAir (Sound me) {
  290. integer n;
  291. double sum2 = getSumOfSquares (me, 0.0, 0.0, & n);
  292. return isdefined (sum2) ? sum2 * my dx / (400.0 * my ny) : undefined;
  293. }
  294. double Sound_getIntensity_dB (Sound me) {
  295. integer n;
  296. double sum2 = getSumOfSquares (me, 0.0, 0.0, & n);
  297. return isdefined (sum2) && sum2 != 0.0 ? 10.0 * log10 (sum2 / (n * my ny) / 4.0e-10) : undefined;
  298. }
  299. double Sound_getPowerInAir (Sound me) {
  300. integer n;
  301. double sum2 = getSumOfSquares (me, 0, 0, & n);
  302. return ( isdefined (sum2) ? sum2 / (n * my ny) / 400.0 : undefined );
  303. }
  304. autoSound Matrix_to_Sound_mono (Matrix me, integer row) {
  305. try {
  306. autoSound thee = Sound_create (1, my xmin, my xmax, my nx, my dx, my x1);
  307. if (row < 0) row = my ny + 1 + row;
  308. if (row < 1) row = 1;
  309. if (row > my ny) row = my ny;
  310. NUMvector_copyElements (my z [row], thy z [1], 1, my nx);
  311. return thee;
  312. } catch (MelderError) {
  313. Melder_throw (me, U": not converted to Sound.");
  314. }
  315. }
  316. autoSound Matrix_to_Sound (Matrix me) {
  317. try {
  318. autoSound thee = Thing_new (Sound);
  319. my structMatrix :: v_copy (thee.get());
  320. return thee;
  321. } catch (MelderError) {
  322. Melder_throw (me, U": not converted to Sound.");
  323. }
  324. }
  325. autoMatrix Sound_to_Matrix (Sound me) {
  326. try {
  327. autoMatrix thee = Thing_new (Matrix);
  328. my structMatrix :: v_copy (thee.get());
  329. return thee;
  330. } catch (MelderError) {
  331. Melder_throw (me, U": not converted to Matrix.");
  332. }
  333. }
  334. autoSound Sound_upsample (Sound me) {
  335. try {
  336. integer nfft = 1;
  337. while (nfft < my nx + 2000) nfft *= 2;
  338. autoSound thee = Sound_create (my ny, my xmin, my xmax, my nx * 2, my dx / 2, my x1 - my dx / 4);
  339. for (integer channel = 1; channel <= my ny; channel ++) {
  340. autoVEC data (2 * nfft, kTensorInitializationType::ZERO); // zeroing is important...
  341. NUMvector_copyElements (my z [channel], & data [1000], 1, my nx); // ...because this fills only part of the sound
  342. NUMrealft (data.subview (1, nfft), 1);
  343. integer imin = (integer) (nfft * 0.95);
  344. for (integer i = imin + 1; i <= nfft; i ++) {
  345. data [i] *= ((double) (nfft - i)) / (nfft - imin);
  346. }
  347. data [2] = 0.0;
  348. NUMrealft (data.get(), -1);
  349. double factor = 1.0 / nfft;
  350. for (integer i = 1; i <= thy nx; i ++) {
  351. thy z [channel] [i] = data [i + 2000] * factor;
  352. }
  353. }
  354. return thee;
  355. } catch (MelderError) {
  356. Melder_throw (me, U": not upsampled.");
  357. }
  358. }
  359. autoSound Sound_resample (Sound me, double samplingFrequency, integer precision) {
  360. double upfactor = samplingFrequency * my dx;
  361. if (fabs (upfactor - 2) < 1e-6) return Sound_upsample (me);
  362. if (fabs (upfactor - 1) < 1e-6) return Data_copy (me);
  363. try {
  364. integer numberOfSamples = Melder_iround ((my xmax - my xmin) * samplingFrequency);
  365. if (numberOfSamples < 1)
  366. Melder_throw (U"The resampled Sound would have no samples.");
  367. autoSound filtered;
  368. bool weNeedAnAntiAliasingFilter = ( upfactor < 1.0 );
  369. if (weNeedAnAntiAliasingFilter) {
  370. integer nfft = 1, antiTurnAround = 1000;
  371. while (nfft < my nx + antiTurnAround * 2) nfft *= 2;
  372. autoVEC data (nfft, kTensorInitializationType::RAW); // will be zeroed in every turn of the loop
  373. filtered = Sound_create (my ny, my xmin, my xmax, my nx, my dx, my x1);
  374. for (integer channel = 1; channel <= my ny; channel ++) {
  375. for (integer i = 1; i <= nfft; i ++) {
  376. data [i] = 0.0;
  377. }
  378. NUMvector_copyElements (my z [channel], & data [antiTurnAround], 1, my nx);
  379. NUMrealft (data.get(), 1); // go to the frequency domain
  380. for (integer i = Melder_ifloor (upfactor * nfft); i <= nfft; i ++) {
  381. data [i] = 0.0; // filter away high frequencies
  382. }
  383. data [2] = 0.0;
  384. NUMrealft (data.get(), -1); // return to the time domain
  385. double factor = 1.0 / nfft;
  386. double *to = filtered -> z [channel];
  387. for (integer i = 1; i <= my nx; i ++) {
  388. to [i] = data [i + antiTurnAround] * factor;
  389. }
  390. }
  391. me = filtered.get(); // reference copy; remove at end
  392. }
  393. autoSound thee = Sound_create (my ny, my xmin, my xmax, numberOfSamples, 1.0 / samplingFrequency,
  394. 0.5 * (my xmin + my xmax - (numberOfSamples - 1) / samplingFrequency));
  395. for (integer channel = 1; channel <= my ny; channel ++) {
  396. double *from = my z [channel];
  397. double *to = thy z [channel];
  398. if (precision <= 1) {
  399. for (integer i = 1; i <= numberOfSamples; i ++) {
  400. double x = Sampled_indexToX (thee.get(), i);
  401. double index = Sampled_xToIndex (me, x);
  402. integer leftSample = Melder_ifloor (index);
  403. double fraction = index - leftSample;
  404. to [i] = leftSample < 1 || leftSample >= my nx ? 0.0 :
  405. (1 - fraction) * from [leftSample] + fraction * from [leftSample + 1];
  406. }
  407. } else {
  408. for (integer i = 1; i <= numberOfSamples; i ++) {
  409. double x = Sampled_indexToX (thee.get(), i);
  410. double index = Sampled_xToIndex (me, x);
  411. to [i] = NUM_interpolate_sinc (my z [channel], my nx, index, precision);
  412. }
  413. }
  414. }
  415. return thee;
  416. } catch (MelderError) {
  417. Melder_throw (me, U": not resampled.");
  418. }
  419. }
  420. autoSound Sounds_append (Sound me, double silenceDuration, Sound thee) {
  421. try {
  422. integer nx_silence = Melder_iround (silenceDuration / my dx), nx = my nx + nx_silence + thy nx;
  423. if (my ny != thy ny)
  424. Melder_throw (U"The numbers of channels are not equal (e.g. one is mono, the other stereo).");
  425. if (my dx != thy dx)
  426. Melder_throw (U"The sampling frequencies are not equal.");
  427. autoSound him = Sound_create (my ny, 0.0, nx * my dx, nx, my dx, 0.5 * my dx);
  428. for (integer channel = 1; channel <= my ny; channel ++) {
  429. NUMvector_copyElements (my z [channel], his z [channel], 1, my nx);
  430. NUMvector_copyElements (thy z [channel], his z [channel] + my nx + nx_silence, 1, thy nx);
  431. }
  432. return him;
  433. } catch (MelderError) {
  434. Melder_throw (me, U" & ", thee, U": not appended.");
  435. }
  436. }
  437. autoSound Sounds_concatenate (OrderedOf<structSound>& list, double overlapTime) {
  438. try {
  439. integer numberOfChannels = 0, nx = 0, numberOfSmoothingSamples;
  440. double dx = 0.0;
  441. for (integer i = 1; i <= list.size; i ++) {
  442. Sound sound = list.at [i];
  443. if (numberOfChannels == 0) {
  444. numberOfChannels = sound -> ny;
  445. } else if (sound -> ny != numberOfChannels) {
  446. Melder_throw (U"To concatenate sounds, their numbers of channels (mono, stereo) should be equal.");
  447. }
  448. if (dx == 0.0) {
  449. dx = sound -> dx;
  450. } else if (sound -> dx != dx) {
  451. Melder_throw (U"To concatenate sounds, their sampling frequencies should be equal.\n"
  452. U"You could resample one or more of the sounds before concatenating.");
  453. }
  454. nx += sound -> nx;
  455. }
  456. numberOfSmoothingSamples = Melder_iround (overlapTime / dx);
  457. autoSound thee = Sound_create (numberOfChannels, 0.0, nx * dx, nx, dx, 0.5 * dx);
  458. autoVEC smoother;
  459. if (numberOfSmoothingSamples > 0) {
  460. smoother = autoVEC (numberOfSmoothingSamples, kTensorInitializationType::RAW);
  461. double factor = NUMpi / numberOfSmoothingSamples;
  462. for (integer i = 1; i <= numberOfSmoothingSamples; i ++) {
  463. smoother [i] = 0.5 - 0.5 * cos (factor * (i - 0.5));
  464. }
  465. }
  466. nx = 0;
  467. for (integer i = 1; i <= list.size; i ++) {
  468. Sound sound = list.at [i];
  469. if (numberOfSmoothingSamples > 2 * sound -> nx)
  470. Melder_throw (U"At least one of the sounds is shorter than twice the overlap time.\nChoose a shorter overlap time.");
  471. bool thisIsTheFirstSound = ( i == 1 );
  472. bool thisIsTheLastSound = ( i == list.size );
  473. bool weNeedSmoothingAtTheStartOfThisSound = ! thisIsTheFirstSound;
  474. bool weNeedSmoothingAtTheEndOfThisSound = ! thisIsTheLastSound;
  475. integer numberOfSmoothingSamplesAtTheStartOfThisSound = weNeedSmoothingAtTheStartOfThisSound ? numberOfSmoothingSamples : 0;
  476. integer numberOfSmoothingSamplesAtTheEndOfThisSound = weNeedSmoothingAtTheEndOfThisSound ? numberOfSmoothingSamples : 0;
  477. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  478. for (integer j = 1, mySample = 1, thySample = mySample + nx;
  479. j <= numberOfSmoothingSamplesAtTheStartOfThisSound;
  480. j ++, mySample ++, thySample ++)
  481. {
  482. thy z [channel] [thySample] += sound -> z [channel] [mySample] * smoother [j]; // add
  483. }
  484. NUMvector_copyElements (sound -> z [channel], thy z [channel] + nx,
  485. 1 + numberOfSmoothingSamplesAtTheStartOfThisSound, sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound);
  486. for (integer j = 1, mySample = sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound + 1, thySample = mySample + nx;
  487. j <= numberOfSmoothingSamplesAtTheEndOfThisSound;
  488. j ++, mySample ++, thySample ++)
  489. {
  490. thy z [channel] [thySample] = sound -> z [channel] [mySample] * smoother [numberOfSmoothingSamplesAtTheEndOfThisSound + 1 - j]; // replace (or add, which is the same since it's all zeroes to start with)
  491. }
  492. }
  493. nx += sound -> nx - numberOfSmoothingSamplesAtTheEndOfThisSound;
  494. }
  495. thy nx -= numberOfSmoothingSamples * (list.size - 1);
  496. Melder_assert (thy nx == nx);
  497. thy xmax = thy nx * dx;
  498. return thee;
  499. } catch (MelderError) {
  500. Melder_throw (U"Sounds not concatenated.");
  501. }
  502. }
  503. autoSound Sounds_convolve (Sound me, Sound thee, kSounds_convolve_scaling scaling, kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
  504. try {
  505. if (my ny > 1 && thy ny > 1 && my ny != thy ny)
  506. Melder_throw (U"The numbers of channels of the two sounds have to be equal or 1.");
  507. if (my dx != thy dx)
  508. Melder_throw (U"The sampling frequencies of the two sounds have to be equal.");
  509. integer n1 = my nx, n2 = thy nx;
  510. integer n3 = n1 + n2 - 1, nfft = 1;
  511. while (nfft < n3) nfft *= 2;
  512. autoVEC data1 (nfft, kTensorInitializationType::RAW);
  513. autoVEC data2 (nfft, kTensorInitializationType::RAW);
  514. integer numberOfChannels = my ny > thy ny ? my ny : thy ny;
  515. autoSound him = Sound_create (numberOfChannels, my xmin + thy xmin, my xmax + thy xmax, n3, my dx, my x1 + thy x1);
  516. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  517. double *a = my z [my ny == 1 ? 1 : channel];
  518. for (integer i = n1; i > 0; i --) data1 [i] = a [i];
  519. for (integer i = n1 + 1; i <= nfft; i ++) data1 [i] = 0.0;
  520. a = thy z [thy ny == 1 ? 1 : channel];
  521. for (integer i = n2; i > 0; i --) data2 [i] = a [i];
  522. for (integer i = n2 + 1; i <= nfft; i ++) data2 [i] = 0.0;
  523. NUMrealft (data1.get(), 1);
  524. NUMrealft (data2.get(), 1);
  525. data2 [1] *= data1 [1];
  526. data2 [2] *= data1 [2];
  527. for (integer i = 3; i <= nfft; i += 2) {
  528. double temp = data1 [i] * data2 [i] - data1 [i + 1] * data2 [i + 1];
  529. data2 [i + 1] = data1 [i] * data2 [i + 1] + data1 [i + 1] * data2 [i];
  530. data2 [i] = temp;
  531. }
  532. NUMrealft (data2.get(), -1);
  533. a = him -> z [channel];
  534. for (integer i = 1; i <= n3; i ++) {
  535. a [i] = data2 [i];
  536. }
  537. }
  538. switch (signalOutsideTimeDomain) {
  539. case kSounds_convolve_signalOutsideTimeDomain::ZERO: {
  540. // do nothing
  541. } break;
  542. case kSounds_convolve_signalOutsideTimeDomain::SIMILAR: {
  543. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  544. double *a = his z [channel];
  545. double edge = n1 < n2 ? n1 : n2;
  546. for (integer i = 1; i < edge; i ++) {
  547. double factor = edge / i;
  548. a [i] *= factor;
  549. a [n3 + 1 - i] *= factor;
  550. }
  551. }
  552. } break;
  553. //case kSounds_convolve_signalOutsideTimeDomain_PERIODIC: {
  554. // do nothing
  555. //} break;
  556. default: Melder_fatal (U"Sounds_convolve: unimplemented outside-time-domain strategy ", (int) signalOutsideTimeDomain);
  557. }
  558. switch (scaling) {
  559. case kSounds_convolve_scaling::INTEGRAL: {
  560. Vector_multiplyByScalar (him.get(), my dx / nfft);
  561. } break;
  562. case kSounds_convolve_scaling::SUM: {
  563. Vector_multiplyByScalar (him.get(), 1.0 / nfft);
  564. } break;
  565. case kSounds_convolve_scaling::NORMALIZE: {
  566. double normalizationFactor = Matrix_getNorm (me) * Matrix_getNorm (thee);
  567. if (normalizationFactor != 0.0) {
  568. Vector_multiplyByScalar (him.get(), 1.0 / nfft / normalizationFactor);
  569. }
  570. } break;
  571. case kSounds_convolve_scaling::PEAK_099: {
  572. Vector_scale (him.get(), 0.99);
  573. } break;
  574. default: Melder_fatal (U"Sounds_convolve: unimplemented scaling ", (int) scaling);
  575. }
  576. return him;
  577. } catch (MelderError) {
  578. Melder_throw (me, U" & ", thee, U": not convolved.");
  579. }
  580. }
  581. autoSound Sounds_crossCorrelate (Sound me, Sound thee, kSounds_convolve_scaling scaling, kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
  582. try {
  583. if (my ny > 1 && thy ny > 1 && my ny != thy ny)
  584. Melder_throw (U"The numbers of channels of the two sounds have to be equal or 1.");
  585. if (my dx != thy dx)
  586. Melder_throw (U"The sampling frequencies of the two sounds have to be equal.");
  587. integer numberOfChannels = my ny > thy ny ? my ny : thy ny;
  588. integer n1 = my nx, n2 = thy nx;
  589. integer n3 = n1 + n2 - 1, nfft = 1;
  590. while (nfft < n3) nfft *= 2;
  591. autoVEC data1 (nfft, kTensorInitializationType::RAW);
  592. autoVEC data2 (nfft, kTensorInitializationType::RAW);
  593. double my_xlast = my x1 + (n1 - 1) * my dx;
  594. autoSound him = Sound_create (numberOfChannels, thy xmin - my xmax, thy xmax - my xmin, n3, my dx, thy x1 - my_xlast);
  595. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  596. double *a = my z [my ny == 1 ? 1 : channel];
  597. for (integer i = n1; i > 0; i --) data1 [i] = a [i];
  598. for (integer i = n1 + 1; i <= nfft; i ++) data1 [i] = 0.0;
  599. a = thy z [thy ny == 1 ? 1 : channel];
  600. for (integer i = n2; i > 0; i --) data2 [i] = a [i];
  601. for (integer i = n2 + 1; i <= nfft; i ++) data2 [i] = 0.0;
  602. NUMrealft (data1.get(), 1);
  603. NUMrealft (data2.get(), 1);
  604. data2 [1] *= data1 [1];
  605. data2 [2] *= data1 [2];
  606. for (integer i = 3; i <= nfft; i += 2) {
  607. double temp = data1 [i] * data2 [i] + data1 [i + 1] * data2 [i + 1]; // reverse me by taking the conjugate of data1
  608. data2 [i + 1] = data1 [i] * data2 [i + 1] - data1 [i + 1] * data2 [i]; // reverse me by taking the conjugate of data1
  609. data2 [i] = temp;
  610. }
  611. NUMrealft (data2.get(), -1);
  612. a = him -> z [channel];
  613. for (integer i = 1; i < n1; i ++) {
  614. a [i] = data2 [i + (nfft - (n1 - 1))]; // data for the first part ("negative lags") is at the end of data2
  615. }
  616. for (integer i = 1; i <= n2; i ++) {
  617. a [i + (n1 - 1)] = data2 [i]; // data for the second part ("positive lags") is at the beginning of data2
  618. }
  619. }
  620. switch (signalOutsideTimeDomain) {
  621. case kSounds_convolve_signalOutsideTimeDomain::ZERO: {
  622. // do nothing
  623. } break;
  624. case kSounds_convolve_signalOutsideTimeDomain::SIMILAR: {
  625. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  626. double *a = his z [channel];
  627. double edge = n1 < n2 ? n1 : n2;
  628. for (integer i = 1; i < edge; i ++) {
  629. double factor = edge / i;
  630. a [i] *= factor;
  631. a [n3 + 1 - i] *= factor;
  632. }
  633. }
  634. } break;
  635. //case kSounds_convolve_signalOutsideTimeDomain_PERIODIC: {
  636. // do nothing
  637. //} break;
  638. default: Melder_fatal (U"Sounds_crossCorrelate: unimplemented outside-time-domain strategy ", (int) signalOutsideTimeDomain);
  639. }
  640. switch (scaling) {
  641. case kSounds_convolve_scaling::INTEGRAL: {
  642. Vector_multiplyByScalar (him.get(), my dx / nfft);
  643. } break;
  644. case kSounds_convolve_scaling::SUM: {
  645. Vector_multiplyByScalar (him.get(), 1.0 / nfft);
  646. } break;
  647. case kSounds_convolve_scaling::NORMALIZE: {
  648. double normalizationFactor = Matrix_getNorm (me) * Matrix_getNorm (thee);
  649. if (normalizationFactor != 0.0) {
  650. Vector_multiplyByScalar (him.get(), 1.0 / nfft / normalizationFactor);
  651. }
  652. } break;
  653. case kSounds_convolve_scaling::PEAK_099: {
  654. Vector_scale (him.get(), 0.99);
  655. } break;
  656. default: Melder_fatal (U"Sounds_crossCorrelate: unimplemented scaling ", (int) scaling);
  657. }
  658. return him;
  659. } catch (MelderError) {
  660. Melder_throw (me, U" & ", thee, U": not cross-correlated.");
  661. }
  662. }
  663. autoSound Sound_autoCorrelate (Sound me, kSounds_convolve_scaling scaling, kSounds_convolve_signalOutsideTimeDomain signalOutsideTimeDomain) {
  664. try {
  665. integer numberOfChannels = my ny, n1 = my nx, n2 = n1 + n1 - 1, nfft = 1;
  666. while (nfft < n2) nfft *= 2;
  667. autoVEC data (nfft, kTensorInitializationType::RAW);
  668. double my_xlast = my x1 + (n1 - 1) * my dx;
  669. autoSound thee = Sound_create (numberOfChannels, my xmin - my xmax, my xmax - my xmin, n2, my dx, my x1 - my_xlast);
  670. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  671. double *a = my z [channel];
  672. for (integer i = n1; i > 0; i --) data [i] = a [i];
  673. for (integer i = n1 + 1; i <= nfft; i ++) data [i] = 0.0;
  674. NUMrealft (data.get(), 1);
  675. data [1] *= data [1];
  676. data [2] *= data [2];
  677. for (integer i = 3; i <= nfft; i += 2) {
  678. data [i] = data [i] * data [i] + data [i + 1] * data [i + 1];
  679. data [i + 1] = 0.0; // reverse me by taking the conjugate of data1
  680. }
  681. NUMrealft (data.get(), -1);
  682. a = thy z [channel];
  683. for (integer i = 1; i < n1; i ++) {
  684. a [i] = data [i + (nfft - (n1 - 1))]; // data for the first part ("negative lags") is at the end of data
  685. }
  686. for (integer i = 1; i <= n1; i ++) {
  687. a [i + (n1 - 1)] = data [i]; // data for the second part ("positive lags") is at the beginning of data
  688. }
  689. }
  690. switch (signalOutsideTimeDomain) {
  691. case kSounds_convolve_signalOutsideTimeDomain::ZERO: {
  692. // do nothing
  693. } break;
  694. case kSounds_convolve_signalOutsideTimeDomain::SIMILAR: {
  695. for (integer channel = 1; channel <= numberOfChannels; channel ++) {
  696. double *a = thy z [channel];
  697. double edge = n1;
  698. for (integer i = 1; i < edge; i ++) {
  699. double factor = edge / i;
  700. a [i] *= factor;
  701. a [n2 + 1 - i] *= factor;
  702. }
  703. }
  704. } break;
  705. //case kSounds_convolve_signalOutsideTimeDomain_PERIODIC: {
  706. // do nothing
  707. //} break;
  708. default: Melder_fatal (U"Sounds_autoCorrelate: unimplemented outside-time-domain strategy ", (int) signalOutsideTimeDomain);
  709. }
  710. switch (scaling) {
  711. case kSounds_convolve_scaling::INTEGRAL: {
  712. Vector_multiplyByScalar (thee.get(), my dx / nfft);
  713. } break;
  714. case kSounds_convolve_scaling::SUM: {
  715. Vector_multiplyByScalar (thee.get(), 1.0 / nfft);
  716. } break;
  717. case kSounds_convolve_scaling::NORMALIZE: {
  718. double normalizationFactor = Matrix_getNorm (me) * Matrix_getNorm (me);
  719. if (normalizationFactor != 0.0) {
  720. Vector_multiplyByScalar (thee.get(), 1.0 / nfft / normalizationFactor);
  721. }
  722. } break;
  723. case kSounds_convolve_scaling::PEAK_099: {
  724. Vector_scale (thee.get(), 0.99);
  725. } break;
  726. default: Melder_fatal (U"Sounds_autoCorrelate: unimplemented scaling ", (int) scaling);
  727. }
  728. return thee;
  729. } catch (MelderError) {
  730. Melder_throw (me, U": autocorrelation not computed.");
  731. }
  732. }
  733. void Sound_draw (Sound me, Graphics g,
  734. double tmin, double tmax, double minimum, double maximum, bool garnish, conststring32 method)
  735. {
  736. bool treversed = tmin > tmax;
  737. if (treversed) { double temp = tmin; tmin = tmax; tmax = temp; }
  738. /*
  739. Automatic domain.
  740. */
  741. if (tmin == tmax) {
  742. tmin = my xmin;
  743. tmax = my xmax;
  744. }
  745. /*
  746. Domain expressed in sample numbers.
  747. */
  748. integer ixmin, ixmax;
  749. Matrix_getWindowSamplesX (me, tmin, tmax, & ixmin, & ixmax);
  750. /*
  751. Automatic vertical range.
  752. */
  753. if (minimum == maximum) {
  754. Matrix_getWindowExtrema (me, ixmin, ixmax, 1, my ny, & minimum, & maximum);
  755. if (minimum == maximum) {
  756. minimum -= 1.0;
  757. maximum += 1.0;
  758. }
  759. }
  760. /*
  761. Set coordinates for drawing.
  762. */
  763. Graphics_setInner (g);
  764. for (integer channel = 1; channel <= my ny; channel ++) {
  765. Graphics_setWindow (g, treversed ? tmax : tmin, treversed ? tmin : tmax,
  766. minimum - (my ny - channel) * (maximum - minimum),
  767. maximum + (channel - 1) * (maximum - minimum));
  768. if (str32str (method, U"bars") || str32str (method, U"Bars")) {
  769. for (integer ix = ixmin; ix <= ixmax; ix ++) {
  770. double x = Sampled_indexToX (me, ix);
  771. double y = my z [channel] [ix];
  772. double left = x - 0.5 * my dx, right = x + 0.5 * my dx;
  773. if (y > maximum) y = maximum;
  774. if (left < tmin) left = tmin;
  775. if (right > tmax) right = tmax;
  776. Graphics_line (g, left, y, right, y);
  777. Graphics_line (g, left, y, left, minimum);
  778. Graphics_line (g, right, y, right, minimum);
  779. }
  780. } else if (str32str (method, U"poles") || str32str (method, U"Poles")) {
  781. for (integer ix = ixmin; ix <= ixmax; ix ++) {
  782. double x = Sampled_indexToX (me, ix);
  783. Graphics_line (g, x, 0, x, my z [channel] [ix]);
  784. }
  785. } else if (str32str (method, U"speckles") || str32str (method, U"Speckles")) {
  786. for (integer ix = ixmin; ix <= ixmax; ix ++) {
  787. double x = Sampled_indexToX (me, ix);
  788. Graphics_speckle (g, x, my z [channel] [ix]);
  789. }
  790. } else {
  791. /*
  792. * The default: draw as a curve.
  793. */
  794. Graphics_function (g, my z [channel], ixmin, ixmax,
  795. Matrix_columnToX (me, ixmin), Matrix_columnToX (me, ixmax));
  796. }
  797. }
  798. Graphics_setWindow (g, treversed ? tmax : tmin, treversed ? tmin : tmax, minimum, maximum);
  799. if (garnish && my ny == 2) Graphics_line (g, tmin, 0.5 * (minimum + maximum), tmax, 0.5 * (minimum + maximum));
  800. Graphics_unsetInner (g);
  801. if (garnish) {
  802. Graphics_drawInnerBox (g);
  803. Graphics_textBottom (g, true, U"Time (s)");
  804. Graphics_marksBottom (g, 2, true, true, false);
  805. Graphics_setWindow (g, tmin, tmax, minimum - (my ny - 1) * (maximum - minimum), maximum);
  806. Graphics_markLeft (g, minimum, true, true, false, nullptr);
  807. Graphics_markLeft (g, maximum, true, true, false, nullptr);
  808. if (minimum != 0.0 && maximum != 0.0 && (minimum > 0.0) != (maximum > 0.0)) {
  809. Graphics_markLeft (g, 0.0, true, true, true, nullptr);
  810. }
  811. if (my ny == 2) {
  812. Graphics_setWindow (g, treversed ? tmax : tmin, treversed ? tmin : tmax, minimum, maximum + (my ny - 1) * (maximum - minimum));
  813. Graphics_markRight (g, minimum, true, true, false, nullptr);
  814. Graphics_markRight (g, maximum, true, true, false, nullptr);
  815. if (minimum != 0.0 && maximum != 0.0 && (minimum > 0.0) != (maximum > 0.0)) {
  816. Graphics_markRight (g, 0.0, true, true, true, nullptr);
  817. }
  818. }
  819. }
  820. }
  821. static double interpolate (Sound me, integer i1, integer channel)
  822. /* Precondition: my z [1] [i1] != my z [1] [i1 + 1]; */
  823. {
  824. integer i2 = i1 + 1;
  825. double x1 = Sampled_indexToX (me, i1), x2 = Sampled_indexToX (me, i2);
  826. double y1 = my z [channel] [i1], y2 = my z [channel] [i2];
  827. return x1 + (x2 - x1) * y1 / (y1 - y2); // linear
  828. }
  829. double Sound_getNearestZeroCrossing (Sound me, double position, integer channel) {
  830. double *amplitude = my z [channel];
  831. integer leftSample = Sampled_xToLowIndex (me, position);
  832. integer rightSample = leftSample + 1, ileft, iright;
  833. double leftZero, rightZero;
  834. /* Are we already at a zero crossing? */
  835. if (leftSample >= 1 && rightSample <= my nx &&
  836. (amplitude [leftSample] >= 0.0) !=
  837. (amplitude [rightSample] >= 0.0))
  838. {
  839. return interpolate (me, leftSample, channel);
  840. }
  841. /* Search to the left. */
  842. if (leftSample > my nx) return undefined;
  843. for (ileft = leftSample - 1; ileft >= 1; ileft --)
  844. if ((amplitude [ileft] >= 0.0) != (amplitude [ileft + 1] >= 0.0))
  845. {
  846. leftZero = interpolate (me, ileft, channel);
  847. break;
  848. }
  849. /* Search to the right. */
  850. if (rightSample < 1) return undefined;
  851. for (iright = rightSample + 1; iright <= my nx; iright ++)
  852. if ((amplitude [iright] >= 0.0) != (amplitude [iright - 1] >= 0.0))
  853. {
  854. rightZero = interpolate (me, iright - 1, channel);
  855. break;
  856. }
  857. if (ileft < 1 && iright > my nx) return undefined;
  858. return ileft < 1 ? rightZero : iright > my nx ? leftZero :
  859. position - leftZero < rightZero - position ? leftZero : rightZero;
  860. }
  861. void Sound_setZero (Sound me, double tmin_in, double tmax_in, bool roundTimesToNearestZeroCrossing) {
  862. Function_unidirectionalAutowindow (me, & tmin_in, & tmax_in);
  863. Function_intersectRangeWithDomain (me, & tmin_in, & tmax_in);
  864. for (integer channel = 1; channel <= my ny; channel ++) {
  865. double tmin = tmin_in, tmax = tmax_in;
  866. if (roundTimesToNearestZeroCrossing) {
  867. if (tmin > my xmin) tmin = Sound_getNearestZeroCrossing (me, tmin_in, channel);
  868. if (tmax < my xmax) tmax = Sound_getNearestZeroCrossing (me, tmax_in, channel);
  869. }
  870. if (isundef (tmin)) tmin = my xmin;
  871. if (isundef (tmax)) tmax = my xmax;
  872. integer imin, imax;
  873. Sampled_getWindowSamples (me, tmin, tmax, & imin, & imax);
  874. for (integer i = imin; i <= imax; i ++) {
  875. my z [channel] [i] = 0.0;
  876. }
  877. }
  878. }
  879. autoSound Sound_createAsPureTone (integer numberOfChannels, double startingTime, double endTime,
  880. double sampleRate, double frequency, double amplitude, double fadeInDuration, double fadeOutDuration)
  881. {
  882. try {
  883. double numberOfSamples_f = round ((endTime - startingTime) * sampleRate);
  884. if (numberOfSamples_f > (double) INT32_MAX)
  885. Melder_throw (U"Cannot create sounds with more than ", Melder_bigInteger (INT32_MAX), U" samples, because they cannot be saved to disk.");
  886. autoSound me = Sound_create (numberOfChannels, startingTime, endTime, (integer) numberOfSamples_f,
  887. 1.0 / sampleRate, startingTime + 0.5 / sampleRate);
  888. for (integer isamp = 1; isamp <= my nx; isamp ++) {
  889. double time = my x1 + (isamp - 1) * my dx;
  890. double value = amplitude * sin (NUM2pi * frequency * time);
  891. double timeFromStart = time - startingTime;
  892. if (timeFromStart < fadeInDuration)
  893. value *= 0.5 - 0.5 * cos (NUMpi * timeFromStart / fadeInDuration);
  894. double timeFromEnd = endTime - time;
  895. if (timeFromEnd < fadeOutDuration)
  896. value *= 0.5 - 0.5 * cos (NUMpi * timeFromEnd / fadeOutDuration);
  897. for (integer ichan = 1; ichan <= my ny; ichan ++) {
  898. my z [ichan] [isamp] = value;
  899. }
  900. }
  901. return me;
  902. } catch (MelderError) {
  903. Melder_throw (U"Sound not created from tone complex.");
  904. }
  905. }
  906. autoSound Sound_createAsToneComplex (double startTime, double endTime, double samplingFrequency,
  907. int phase, double frequencyStep, double firstFrequency, double ceiling, integer numberOfComponents)
  908. {
  909. try {
  910. if (frequencyStep == 0.0)
  911. Melder_throw (U"The frequency step should not be zero.");
  912. /*
  913. Translate default firstFrequency.
  914. */
  915. if (firstFrequency <= 0.0) firstFrequency = frequencyStep;
  916. double firstOmega = 2 * NUMpi * firstFrequency;
  917. /*
  918. Translate default ceiling.
  919. */
  920. double omegaStep = 2 * NUMpi * frequencyStep, nyquistFrequency = 0.5 * samplingFrequency;
  921. if (ceiling <= 0.0 || ceiling > nyquistFrequency) ceiling = nyquistFrequency;
  922. /*
  923. Translate number of components.
  924. */
  925. integer maximumNumberOfComponents = Melder_ifloor ((ceiling - firstFrequency) / frequencyStep) + 1;
  926. if (numberOfComponents <= 0 || numberOfComponents > maximumNumberOfComponents)
  927. numberOfComponents = maximumNumberOfComponents;
  928. if (numberOfComponents < 1)
  929. Melder_throw (U"There would be zero sine waves.");
  930. /*
  931. Generate the Sound.
  932. */
  933. double factor = 0.99 / numberOfComponents;
  934. autoSound me = Sound_create (1, startTime, endTime, Melder_iround ((endTime - startTime) * samplingFrequency),
  935. 1.0 / samplingFrequency, startTime + 0.5 / samplingFrequency);
  936. double *amplitude = my z [1];
  937. for (integer isamp = 1; isamp <= my nx; isamp ++) {
  938. double value = 0.0, t = Sampled_indexToX (me.get(), isamp);
  939. double omegaStepT = omegaStep * t, firstOmegaT = firstOmega * t;
  940. if (phase == Sound_TONE_COMPLEX_SINE) {
  941. for (integer icomp = 1; icomp <= numberOfComponents; icomp ++)
  942. value += sin (firstOmegaT + (icomp - 1) * omegaStepT);
  943. } else {
  944. for (integer icomp = 1; icomp <= numberOfComponents; icomp ++)
  945. value += cos (firstOmegaT + (icomp - 1) * omegaStepT);
  946. }
  947. amplitude [isamp] = value * factor;
  948. }
  949. return me;
  950. } catch (MelderError) {
  951. Melder_throw (U"Sound not created as tone complex.");
  952. }
  953. }
  954. void Sound_multiplyByWindow (Sound me, kSound_windowShape windowShape) {
  955. for (integer channel = 1; channel <= my ny; channel ++) {
  956. integer n = my nx;
  957. double *amp = my z [channel];
  958. switch (windowShape) {
  959. case kSound_windowShape::RECTANGULAR: {
  960. ;
  961. } break; case kSound_windowShape::TRIANGULAR: { // "Bartlett"
  962. for (integer i = 1; i <= n; i ++) { double phase = (double) i / n; // 0..1
  963. amp [i] *= 1.0 - fabs ((2.0 * phase - 1.0)); }
  964. } break; case kSound_windowShape::PARABOLIC: { // "Welch"
  965. for (integer i = 1; i <= n; i ++) { double phase = (double) i / n;
  966. amp [i] *= 1.0 - (2.0 * phase - 1.0) * (2.0 * phase - 1.0); }
  967. } break; case kSound_windowShape::HANNING: {
  968. for (integer i = 1; i <= n; i ++) { double phase = (double) i / n;
  969. amp [i] *= 0.5 * (1.0 - cos (2.0 * NUMpi * phase)); }
  970. } break; case kSound_windowShape::HAMMING: {
  971. for (integer i = 1; i <= n; i ++) { double phase = (double) i / n;
  972. amp [i] *= 0.54 - 0.46 * cos (2.0 * NUMpi * phase); }
  973. } break; case kSound_windowShape::GAUSSIAN_1: {
  974. double imid = 0.5 * (n + 1), edge = exp (-3.0), onebyedge1 = 1.0 / (1.0 - edge); // -0.5..+0.5
  975. for (integer i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n;
  976. amp [i] *= (exp (-12.0 * phase * phase) - edge) * onebyedge1; }
  977. } break; case kSound_windowShape::GAUSSIAN_2: {
  978. double imid = 0.5 * (double) (n + 1), edge = exp (-12.0), onebyedge1 = 1.0 / (1.0 - edge);
  979. for (integer i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n;
  980. amp [i] *= (exp (-48.0 * phase * phase) - edge) * onebyedge1; }
  981. } break; case kSound_windowShape::GAUSSIAN_3: {
  982. double imid = 0.5 * (double) (n + 1), edge = exp (-27.0), onebyedge1 = 1.0 / (1.0 - edge);
  983. for (integer i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n;
  984. amp [i] *= (exp (-108.0 * phase * phase) - edge) * onebyedge1; }
  985. } break; case kSound_windowShape::GAUSSIAN_4: {
  986. double imid = 0.5 * (double) (n + 1), edge = exp (-48.0), onebyedge1 = 1.0 / (1.0 - edge);
  987. for (integer i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n;
  988. amp [i] *= (exp (-192.0 * phase * phase) - edge) * onebyedge1; }
  989. } break; case kSound_windowShape::GAUSSIAN_5: {
  990. double imid = 0.5 * (double) (n + 1), edge = exp (-75.0), onebyedge1 = 1.0 / (1.0 - edge);
  991. for (integer i = 1; i <= n; i ++) { double phase = ((double) i - imid) / n;
  992. amp [i] *= (exp (-300.0 * phase * phase) - edge) * onebyedge1; }
  993. } break; case kSound_windowShape::KAISER_1: {
  994. double imid = 0.5 * (double) (n + 1);
  995. double factor = 1.0 / NUMbessel_i0_f (2 * NUMpi);
  996. for (integer i = 1; i <= n; i ++) { double phase = 2.0 * ((double) i - imid) / n; // -1..+1
  997. double root = 1.0 - phase * phase;
  998. amp [i] *= root <= 0.0 ? 0.0 : factor * NUMbessel_i0_f (2.0 * NUMpi * sqrt (root)); }
  999. } break; case kSound_windowShape::KAISER_2: {
  1000. double imid = 0.5 * (double) (n + 1);
  1001. double factor = 1.0 / NUMbessel_i0_f (2 * NUMpi * NUMpi + 0.5);
  1002. for (integer i = 1; i <= n; i ++) { double phase = 2.0 * ((double) i - imid) / n; // -1..+1
  1003. double root = 1.0 - phase * phase;
  1004. amp [i] *= root <= 0.0 ? 0.0 : factor * NUMbessel_i0_f ((2.0 * NUMpi * NUMpi + 0.5) * sqrt (root)); }
  1005. } break; default: {
  1006. }
  1007. }
  1008. }
  1009. }
  1010. void Sound_scaleIntensity (Sound me, double newAverageIntensity) {
  1011. double currentIntensity = Sound_getIntensity_dB (me), factor;
  1012. if (isundef (currentIntensity)) return;
  1013. factor = pow (10, (newAverageIntensity - currentIntensity) / 20.0);
  1014. for (integer channel = 1; channel <= my ny; channel ++) {
  1015. for (integer i = 1; i <= my nx; i ++) {
  1016. my z [channel] [i] *= factor;
  1017. }
  1018. }
  1019. }
  1020. void Sound_overrideSamplingFrequency (Sound me, double rate) {
  1021. my dx = 1 / rate;
  1022. my x1 = my xmin + 0.5 * my dx;
  1023. my xmax = my xmin + my nx * my dx;
  1024. }
  1025. autoSound Sound_extractPart (Sound me, double t1, double t2, kSound_windowShape windowShape, double relativeWidth, bool preserveTimes) {
  1026. try {
  1027. /*
  1028. We do not clip to the Sound's time domain.
  1029. Any samples outside it are taken to be zero.
  1030. */
  1031. /*
  1032. Autowindow.
  1033. */
  1034. if (t1 == t2) { t1 = my xmin; t2 = my xmax; };
  1035. /*
  1036. Allow window tails outside specified domain.
  1037. */
  1038. if (relativeWidth != 1.0) {
  1039. double margin = 0.5 * (relativeWidth - 1) * (t2 - t1);
  1040. t1 -= margin;
  1041. t2 += margin;
  1042. }
  1043. /*
  1044. Determine index range. We use all the real or virtual samples that fit within [t1..t2].
  1045. */
  1046. integer ix1 = 1 + Melder_iceiling ((t1 - my x1) / my dx);
  1047. integer ix2 = 1 + Melder_ifloor ((t2 - my x1) / my dx);
  1048. if (ix2 < ix1) Melder_throw (U"Extracted Sound would contain no samples.");
  1049. /*
  1050. Create sound, optionally shifted to [0..t2-t1].
  1051. */
  1052. autoSound thee = Sound_create (my ny, t1, t2, ix2 - ix1 + 1, my dx, my x1 + (ix1 - 1) * my dx);
  1053. if (! preserveTimes) { thy xmin = 0.0; thy xmax -= t1; thy x1 -= t1; }
  1054. /*
  1055. Copy only *real* samples into the new sound.
  1056. The *virtual* samples will remain at zero.
  1057. */
  1058. for (integer channel = 1; channel <= my ny; channel ++) {
  1059. NUMvector_copyElements (my z [channel], thy z [channel] + 1 - ix1,
  1060. ( ix1 < 1 ? 1 : ix1 ), ( ix2 > my nx ? my nx : ix2 ));
  1061. }
  1062. /*
  1063. Multiply by a window that extends throughout the target domain.
  1064. */
  1065. Sound_multiplyByWindow (thee.get(), windowShape);
  1066. return thee;
  1067. } catch (MelderError) {
  1068. Melder_throw (me, U": part not extracted.");
  1069. }
  1070. }
  1071. autoSound Sound_extractPartForOverlap (Sound me, double t1, double t2, double overlap) {
  1072. try {
  1073. if (t1 == t2) { t1 = my xmin; t2 = my xmax; }; // autowindow
  1074. if (overlap > 0.0) {
  1075. double margin = 0.5 * overlap;
  1076. t1 -= margin;
  1077. t2 += margin;
  1078. }
  1079. if (t1 < my xmin) t1 = my xmin; // clip to my time domain
  1080. if (t2 > my xmax) t2 = my xmax;
  1081. /*
  1082. Determine index range. We use all the real or virtual samples that fit within [t1..t2].
  1083. */
  1084. integer ix1 = 1 + Melder_iceiling ((t1 - my x1) / my dx);
  1085. integer ix2 = 1 + Melder_ifloor ((t2 - my x1) / my dx);
  1086. if (ix2 < ix1) Melder_throw (U"Extracted Sound would contain no samples.");
  1087. /*
  1088. Create sound.
  1089. */
  1090. autoSound thee = Sound_create (my ny, t1, t2, ix2 - ix1 + 1, my dx, my x1 + (ix1 - 1) * my dx);
  1091. thy xmin = 0.0;
  1092. thy xmax -= t1;
  1093. thy x1 -= t1;
  1094. /*
  1095. Copy only *real* samples into the new sound.
  1096. The *virtual* samples will remain at zero.
  1097. */
  1098. for (integer channel = 1; channel <= my ny; channel ++) {
  1099. NUMvector_copyElements (my z [channel], thy z [channel] + 1 - ix1,
  1100. ( ix1 < 1 ? 1 : ix1 ), ( ix2 > my nx ? my nx : ix2 ));
  1101. }
  1102. return thee;
  1103. } catch (MelderError) {
  1104. Melder_throw (me, U": part not extracted.");
  1105. }
  1106. }
  1107. void Sound_filterWithFormants (Sound me, double tmin, double tmax,
  1108. int numberOfFormants, double formant [], double bandwidth [])
  1109. {
  1110. try {
  1111. for (integer channel = 1; channel <= my ny; channel ++) {
  1112. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } // autowindowing
  1113. integer itmin, itmax;
  1114. integer n = Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax);
  1115. if (n <= 2)
  1116. Melder_throw (U"Sound too short.");
  1117. double *amplitude = my z [channel] + itmin - 1; // base 1
  1118. NUMdeemphasize_f (amplitude, n, my dx, 50.0);
  1119. for (int iformant = 1; iformant <= numberOfFormants; iformant ++) {
  1120. NUMfilterSecondOrderSection_fb (amplitude, n, my dx, formant [iformant], bandwidth [iformant]);
  1121. }
  1122. }
  1123. Matrix_scaleAbsoluteExtremum (me, 0.99);
  1124. } catch (MelderError) {
  1125. Melder_throw (me, U": not filtered.");
  1126. }
  1127. }
  1128. autoSound Sound_filter_oneFormant (Sound me, double frequency, double bandwidth) {
  1129. try {
  1130. autoSound thee = Data_copy (me);
  1131. Sound_filterWithOneFormantInplace (thee.get(), frequency, bandwidth);
  1132. return thee;
  1133. } catch (MelderError) {
  1134. Melder_throw (me, U": not filtered (one formant).");
  1135. }
  1136. }
  1137. void Sound_filterWithOneFormantInplace (Sound me, double frequency, double bandwidth) {
  1138. for (integer channel = 1; channel <= my ny; channel ++) {
  1139. NUMfilterSecondOrderSection_fb (my z [channel], my nx, my dx, frequency, bandwidth);
  1140. }
  1141. Matrix_scaleAbsoluteExtremum (me, 0.99);
  1142. }
  1143. autoSound Sound_filter_preemphasis (Sound me, double frequency) {
  1144. try {
  1145. autoSound thee = Data_copy (me);
  1146. Sound_preEmphasis (thee.get(), frequency);
  1147. Matrix_scaleAbsoluteExtremum (thee.get(), 0.99);
  1148. return thee;
  1149. } catch (MelderError) {
  1150. Melder_throw (me, U": not filtered (pre-emphasis).");
  1151. }
  1152. }
  1153. autoSound Sound_filter_deemphasis (Sound me, double frequency) {
  1154. try {
  1155. autoSound thee = Data_copy (me);
  1156. Sound_deEmphasis (thee.get(), frequency);
  1157. Matrix_scaleAbsoluteExtremum (thee.get(), 0.99);
  1158. return thee;
  1159. } catch (MelderError) {
  1160. Melder_throw (me, U": not filtered (de-emphasis).");
  1161. }
  1162. }
  1163. void Sound_reverse (Sound me, double tmin, double tmax) {
  1164. if (tmax <= tmin) { tmin = my xmin; tmax = my xmax; } // autowindowing
  1165. integer itmin, itmax;
  1166. integer n = Sampled_getWindowSamples (me, tmin, tmax, & itmin, & itmax) / 2;
  1167. for (integer channel = 1; channel <= my ny; channel ++) {
  1168. double *amp = my z [channel];
  1169. for (integer i = 0; i < n; i ++) {
  1170. double dummy = amp [itmin + i];
  1171. amp [itmin + i] = amp [itmax - i];
  1172. amp [itmax - i] = dummy;
  1173. }
  1174. }
  1175. }
  1176. autoSound Sounds_crossCorrelate_short (Sound me, Sound thee, double tmin, double tmax, bool normalize) {
  1177. try {
  1178. if (my dx != thy dx)
  1179. Melder_throw (U"Sampling frequencies are not equal.");
  1180. if (my ny != thy ny)
  1181. Melder_throw (U"Numbers of channels are not equal.");
  1182. double dt = my dx;
  1183. double dphase = (thy x1 - my x1) / dt;
  1184. dphase -= Melder_roundDown (dphase); // a number between 0 and 1
  1185. integer i1 = Melder_iceiling (tmin / dt - dphase); // index of first sample if sample at dphase has index 0
  1186. integer i2 = Melder_ifloor (tmax / dt - dphase); // index of last sample if sample at dphase has index 0
  1187. integer nt = i2 - i1 + 1;
  1188. if (nt < 1)
  1189. Melder_throw (U"Window too small.");
  1190. double t1 = (dphase + i1) * dt;
  1191. autoSound him = Sound_create (1, tmin, tmax, nt, dt, t1);
  1192. for (integer i = 1; i <= nt; i ++) {
  1193. integer di = i - 1 + i1;
  1194. for (integer ime = 1; ime <= my nx; ime ++) {
  1195. if (ime + di < 1) continue;
  1196. if (ime + di > thy nx) break;
  1197. for (integer channel = 1; channel <= my ny; channel ++) {
  1198. his z [1] [i] += my z [channel] [ime] * thy z [channel] [ime + di];
  1199. }
  1200. }
  1201. }
  1202. if (normalize) {
  1203. double mypower = 0.0, thypower = 0.0;
  1204. for (integer channel = 1; channel <= my ny; channel ++) {
  1205. for (integer i = 1; i <= my nx; i ++) {
  1206. double value = my z [channel] [i];
  1207. mypower += value * value;
  1208. }
  1209. for (integer i = 1; i <= thy nx; i ++) {
  1210. double value = thy z [channel] [i];
  1211. thypower += value * value;
  1212. }
  1213. }
  1214. if (mypower != 0.0 && thypower != 0.0) {
  1215. double factor = 1.0 / (sqrt (mypower) * sqrt (thypower));
  1216. for (integer i = 1; i <= nt; i ++) {
  1217. his z [1] [i] *= factor;
  1218. }
  1219. }
  1220. } else {
  1221. double factor = dt / my ny;
  1222. for (integer i = 1; i <= nt; i ++) {
  1223. his z [1] [i] *= factor;
  1224. }
  1225. }
  1226. return him;
  1227. } catch (MelderError) {
  1228. Melder_throw (me, U": not cross-correlated.");
  1229. }
  1230. }
  1231. /* End of file Sound.cpp */