gain.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /*
  2. * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /* floatsam version*/
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <cdpmain.h>
  28. #include <modify.h>
  29. #include <modeno.h>
  30. #include <globcon.h>
  31. #include <modify.h>
  32. #include <sfsys.h>
  33. /* RWD added do_clip, peak (later, sort out nChans PEAK stuff... */
  34. static void gain(int samples,double multiplier,double maxnoclip,int *numclipped,
  35. int do_clip,double *peak,dataptr dz);
  36. static int find_max(double *maxfound,dataptr dz);
  37. static int find_maximum(int infile,int *maxloc,int *maxrep,double *maxsamp,dataptr dz);
  38. static void get_max(double *,int,int,int *,int *,dataptr dz);
  39. static int balance(double mratio,dataptr dz);
  40. //TW replaced by peakchunk
  41. //static int write_maxsamp_properties(double,long,long,dataptr dz);
  42. static int do_balance(dataptr dz);
  43. static int gain_process(dataptr dz);
  44. static int get_normalisation_gain(dataptr dz);
  45. static void do_normalise(dataptr dz);
  46. static void do_phase_invert(dataptr dz);
  47. static void find_maxsamp(double *maxfound,dataptr dz);
  48. static int do_multifile_loudness(dataptr dz);
  49. #define MAX_DBGAIN (90)
  50. //TW UPDATE: further updated for floatsams and new-style clipping detection
  51. int gainenv(int samples,int *last_total,double maxnoclip,int *numclipped,int do_clip,double *peak,dataptr dz);
  52. /************************** LOUDNESS_PROCESS *******************************/
  53. int loudness_process(dataptr dz)
  54. {
  55. int n, m;
  56. double maxtime,intime, ratio; /*RWD April 2004 needed to add these */
  57. switch(dz->mode) {
  58. case(LOUD_PROPOR):
  59. case(LOUD_DB_PROPOR):
  60. maxtime = dz->brk[LOUD_GAIN][(dz->brksize[LOUD_GAIN] - 1) * 2];
  61. intime = (double)(dz->insams[0]/dz->infile->channels)/(double)dz->infile->srate;
  62. ratio = intime/maxtime;
  63. for(n=0,m = 0;n < dz->brksize[LOUD_GAIN];n++,m+=2)
  64. dz->brk[LOUD_GAIN][m] = dz->brk[LOUD_GAIN][m] * ratio;
  65. dz->mode = LOUDNESS_GAIN;
  66. break;
  67. case(LOUDNESS_DBGAIN):
  68. if(dz->brksize[LOUD_GAIN]) {
  69. for(n=0,m=1;n < dz->brksize[LOUD_GAIN];n++,m+=2)
  70. dz->brk[LOUD_GAIN][m] = dbtogain(dz->brk[LOUD_GAIN][m]);
  71. } else {
  72. dz->param[LOUD_GAIN] = dbtogain(dz->param[LOUD_GAIN]);
  73. }
  74. break;
  75. }
  76. switch(dz->mode) {
  77. case(LOUDNESS_LOUDEST):
  78. case(LOUDNESS_EQUALISE): return do_multifile_loudness(dz);
  79. case(LOUDNESS_BALANCE): return do_balance(dz);
  80. default: return gain_process(dz);
  81. }
  82. return(FINISHED); /* NOTREACHED */
  83. }
  84. /************************** GAIN_PROCESS *******************************/
  85. int gain_process(dataptr dz)
  86. {
  87. int exit_status;
  88. double maxnoclip = F_MAXSAMP, peakval = 0.0;
  89. //TW UPDATE
  90. int numclipped = 0, last_total = 0;
  91. int clipsamps = 1;
  92. float *buffer = dz->sampbuf[0];
  93. if(dz->true_outfile_stype == SAMP_FLOAT)
  94. if(dz->clip_floatsams == 0)
  95. clipsamps = 0;
  96. switch(dz->mode) {
  97. case(LOUDNESS_NORM):
  98. case(LOUDNESS_SET):
  99. if((exit_status = get_normalisation_gain(dz))!=CONTINUE)
  100. return(exit_status);
  101. break;
  102. }
  103. display_virtual_time(0,dz);
  104. while(dz->samps_left > 0) {
  105. if((exit_status = read_samps(buffer,dz))<0) {
  106. sprintf(errstr,"Cannot read data from sndfile.\n");
  107. return(PROGRAM_ERROR);
  108. }
  109. switch(dz->mode) {
  110. case(LOUDNESS_GAIN):
  111. case(LOUDNESS_DBGAIN):
  112. //TW UPDATE >>
  113. if(dz->brksize[LOUD_GAIN])
  114. gainenv(dz->ssampsread,&last_total,maxnoclip,&numclipped,clipsamps,&peakval,dz);
  115. else if(dz->param[LOUD_GAIN] <= FLTERR) {
  116. sprintf(errstr,"With gain of %lf the soundfile will be reduced to SILENCE!\n",dz->param[LOUD_GAIN]);
  117. return(DATA_ERROR);
  118. } else
  119. //<< TW UPDATE
  120. gain(dz->ssampsread,dz->param[LOUD_GAIN],maxnoclip,&numclipped,clipsamps,&peakval,dz);
  121. break;
  122. case(LOUDNESS_NORM):
  123. case(LOUDNESS_SET):
  124. do_normalise(dz);
  125. break;
  126. case(LOUDNESS_PHASE):
  127. do_phase_invert(dz);
  128. break;
  129. }
  130. if(dz->ssampsread > 0) {
  131. if((exit_status = write_exact_samps(buffer,dz->ssampsread,dz))<0)
  132. return(exit_status);
  133. }
  134. }
  135. if(clipsamps && (numclipped > 0))
  136. sprintf(errstr, "WARNING: %d samples were clipped.\n", numclipped);
  137. dz->peak_fval = peakval;
  138. /*will get written to header automatically*/
  139. return(FINISHED);
  140. }
  141. /************************** GAIN *******************************/
  142. void gain(int samples,double multiplier,double maxnoclip,int *numclipped,
  143. int do_clip,double *peak,dataptr dz)
  144. {
  145. int i;
  146. double s, buf_peak = *peak;
  147. float *buffer = dz->sampbuf[0];
  148. if(multiplier < 0.0)
  149. multiplier = -multiplier;
  150. for(i = 0; i < samples; i++) {
  151. s = buffer[i] * multiplier;
  152. if(s >= 0) {
  153. if(do_clip && (s > maxnoclip)) {
  154. (*numclipped)++;
  155. s = F_MAXSAMP;
  156. }
  157. buf_peak = max(buf_peak,s);
  158. } else {
  159. if(do_clip && (-s > maxnoclip)) {
  160. (*numclipped)++;
  161. s = -F_MAXSAMP;
  162. }
  163. buf_peak = max(buf_peak,-s);
  164. }
  165. buffer[i] = (float) s;
  166. *peak = buf_peak;
  167. }
  168. }
  169. /**************************** DO_NORMALISE ***************************/
  170. /* RWD NB my old floatsam version added a peak_val arg */
  171. void do_normalise(dataptr dz)
  172. {
  173. register int i;
  174. float *buffer = dz->sampbuf[0];
  175. float dgain = (float) dz->param[LOUD_GAIN];
  176. for(i = 0; i < dz->ssampsread; i++) {
  177. //TW float sampl;
  178. //TW sampl = buffer[i] * dgain;
  179. //TW buffer[i] = sampl;
  180. //TW must cast to float anyway, as multiply gives double
  181. buffer[i] = (float)(buffer[i] * dgain);
  182. }
  183. }
  184. /**************************** DO_PHASE_INVERT ***************************/
  185. void do_phase_invert(dataptr dz)
  186. { register int i;
  187. double samplong;
  188. float *buffer = dz->sampbuf[0];
  189. for(i = 0; i < dz->ssampsread; i++) {
  190. samplong = -buffer[i];
  191. samplong = min(samplong,(double)F_MAXSAMP);
  192. buffer[i] = (float)(samplong);
  193. }
  194. }
  195. /****************************** FIND_MAX *************************/
  196. int find_max(double *maxfound,dataptr dz)
  197. {
  198. int exit_status;
  199. float *buffer = dz->sampbuf[0];
  200. display_virtual_time(0L,dz);
  201. while(dz->samps_left != 0) {
  202. if((exit_status = read_samps(buffer,dz))<0) {
  203. sprintf(errstr,"Cannot read data from sndfile.\n");
  204. return(PROGRAM_ERROR);
  205. }
  206. find_maxsamp(maxfound,dz);
  207. display_virtual_time(dz->total_samps_read,dz);
  208. }
  209. /*RWD NB this is a weird step, specifically for this program - balances to
  210. * MAXSAMP if sfile is actually higher than that.
  211. * must delete next line for a generic version!
  212. */
  213. *maxfound = min(*maxfound,(double)F_MAXSAMP); /* e.g. found -32768: substitute 32767 */
  214. return(FINISHED);
  215. }
  216. /**************************** MAXSAMP ***************************/
  217. void find_maxsamp(double *maxfound,dataptr dz)
  218. { register int i;
  219. double k;
  220. float *buffer = dz->sampbuf[0];
  221. for(i = 0; i < dz->ssampsread; i++) {
  222. if((k = fabs(buffer[i])) > *maxfound)
  223. *maxfound = k;
  224. }
  225. return;
  226. }
  227. /**************************** GET_NORMALISATION_GAIN ***************************/
  228. int get_normalisation_gain(dataptr dz)
  229. {
  230. int exit_status;
  231. double maxfound = 0.0;
  232. double loud_level = dz->param[LOUD_LEVEL] * (double)F_MAXSAMP;
  233. print_outmessage_flush("Finding maximum amplitude.\n");
  234. if((exit_status = find_max(&maxfound,dz))<0)
  235. return(exit_status);
  236. if(flteq(maxfound,loud_level)) {
  237. sprintf(errstr,"File is already at the specified level.\n");
  238. return(GOAL_FAILED);
  239. }
  240. if((maxfound > loud_level) && dz->mode == LOUDNESS_NORM) {
  241. sprintf(errstr,"File is already above the specified level.\n");
  242. return(GOAL_FAILED);
  243. }
  244. dz->param[LOUD_GAIN] = loud_level/maxfound;
  245. display_virtual_time(0L,dz);
  246. sprintf(errstr,"Normalising with Gain Factor = %lf\n", dz->param[LOUD_GAIN]);
  247. print_outmessage_flush(errstr);
  248. if(sndseekEx(dz->ifd[0],0L,0)<0) {
  249. sprintf(errstr,"sndseek() failed.\n");
  250. return(SYSTEM_ERROR);
  251. }
  252. reset_filedata_counters(dz);
  253. return(CONTINUE);
  254. }
  255. /***************************** DO_BALANCE ************************/
  256. int do_balance(dataptr dz)
  257. {
  258. int exit_status;
  259. int maxloc;
  260. int maxrep;
  261. double max1, max2;
  262. double mratio;
  263. display_virtual_time(0,dz);
  264. print_outmessage_flush("Getting max level from file 1.\n");
  265. if((exit_status = find_maximum(dz->ifd[0],&maxloc,&maxrep,&max1,dz))<0)
  266. return(exit_status);
  267. if(max1 <= 0) {
  268. sprintf(errstr,"First file has zero amplitude: can't proceed.\n");
  269. return(GOAL_FAILED);
  270. }
  271. //maxloc1 = maxloc;
  272. //maxrep1 = maxrep;
  273. reset_filedata_counters(dz);
  274. dz->samps_left = dz->insams[1];
  275. display_virtual_time(0,dz);
  276. print_outmessage_flush("Getting max level from file 2.\n");
  277. if((exit_status = find_maximum(dz->ifd[1],&maxloc,&maxrep,&max2,dz))<0)
  278. return(exit_status);
  279. mratio = max2/max1;
  280. if(sndseekEx(dz->ifd[0],0,0)<0) {
  281. sprintf(errstr,"sndseek failed.\n");
  282. return(SYSTEM_ERROR);
  283. }
  284. reset_filedata_counters(dz);
  285. display_virtual_time(0,dz);
  286. sprintf(errstr,"Adjusting gain of 1st infile by %lf\n",mratio);
  287. print_outmessage_flush(errstr);
  288. if((exit_status = balance(mratio,dz))< 0)
  289. return(exit_status);
  290. //TW No longer required: takes place in PEAK procedure
  291. // if((exit_status = write_maxsamp_properties(max2,maxloc1,maxrep1,dz))<0)
  292. // return(exit_status);
  293. return(FINISHED);
  294. }
  295. /***************************** BALANCE ************************/
  296. int balance(double mratio,dataptr dz)
  297. {
  298. int exit_status;
  299. int /*samps_read,*/ ssampsread, n;
  300. /*double maxsamp = 0;*/
  301. float *buffer = dz->sampbuf[0];
  302. while((ssampsread = fgetfbufEx(buffer, dz->buflen,dz->ifd[0],0)) > 0) {
  303. for(n=0;n<ssampsread;n++)
  304. buffer[n] = (float) /*round*/((double)buffer[n] * mratio);
  305. if((exit_status = write_exact_samps(buffer,ssampsread,dz))<0)
  306. return(exit_status);
  307. }
  308. if(ssampsread<0) {
  309. sprintf(errstr,"Sound read error.\n");
  310. return(SYSTEM_ERROR);
  311. }
  312. return(FINISHED);
  313. }
  314. /***************************** FIND_MAXIMUM ************************/
  315. int find_maximum(int infile,int *maxloc,int *maxrep,double *maxsamp,dataptr dz)
  316. {
  317. int ssampsread, last_total_ssampsread = 0, total_samps_read = 0;
  318. float *buffer = dz->sampbuf[0];
  319. *maxsamp = 0;
  320. while((ssampsread = fgetfbufEx(buffer, dz->buflen,infile,0)) > 0) {
  321. total_samps_read += ssampsread;
  322. get_max(maxsamp,ssampsread,last_total_ssampsread,maxloc,maxrep,dz);
  323. last_total_ssampsread += ssampsread;
  324. display_virtual_time(total_samps_read,dz);
  325. }
  326. if(ssampsread<0) {
  327. sprintf(errstr,"Sound read error.\n");
  328. return(SYSTEM_ERROR);
  329. }
  330. return(FINISHED);
  331. }
  332. /***************************** GET_MAX ************************/
  333. void get_max(double *maxsamp,int ssampsread,int last_total_ssampsread, int *maxloc, int *maxrep,dataptr dz)
  334. {
  335. register int n;
  336. float thisamp;
  337. float *buffer = dz->sampbuf[0];
  338. for(n=0;n<ssampsread;n++) {
  339. if((thisamp = (float)fabs(buffer[n])) > *maxsamp) {
  340. *maxsamp = thisamp;
  341. *maxloc = last_total_ssampsread + n;
  342. *maxrep = 1;
  343. } else if(flteq(thisamp,*maxsamp)) {
  344. (*maxrep)++;
  345. }
  346. }
  347. return;
  348. }
  349. /********************** WRITE_MAXSAMP_PROPERTIES ***************************/
  350. //
  351. //int write_maxsamp_properties(double max1,long maxloc,long maxrep,dataptr dz)
  352. //{
  353. //
  354. // float maxpfamp = (float)max1;
  355. //
  356. // if(maxloc<0 || maxrep<0) {
  357. // sprintf(errstr,"Failed to establish location and/or repetition-count of max-sample\n");
  358. // return(GOAL_FAILED);
  359. // }
  360. /* TODO: scrap all this for the PEAK chunk instead! */
  361. //* don't store in 'maxamp' as this is (long) in old files:
  362. // if(sndputprop(dz->ofd, "maxpfamp", (char *)&maxpfamp, sizeof(float)) < 0) {
  363. // sprintf(errstr,"Can't write new max-sample to sndfile.\n");
  364. // return(PROGRAM_ERROR);
  365. // }
  366. // if(sndputprop(dz->ofd, "maxloc", (char *)&maxloc, sizeof(long)) < 0) {
  367. // sprintf(errstr,"Can't write location of max-sample to sndfile.\n");
  368. // return(PROGRAM_ERROR);
  369. // }
  370. // if(sndputprop(dz->ofd, "maxrep", (char *)&maxrep, sizeof(long)) < 0) {
  371. // sprintf(errstr,"Can't write repeat-count of max-sample to sndfile.\n");
  372. // return(PROGRAM_ERROR);
  373. // }
  374. // return(FINISHED);
  375. //}
  376. /********************** DO_MULTIFILE_LOUDNESS ***************************/
  377. int do_multifile_loudness(dataptr dz)
  378. {
  379. int exit_status;
  380. double *greater, greatest = 0.0, maxfound;
  381. /*RWD*/
  382. double dbamp;
  383. int clipsamps = 1;
  384. double peak_val = 0.0;
  385. int orig_ifd = dz->ifd[0];
  386. //TW REVISED Dec 2002
  387. // int n, do_gain, namelen, maxno = 0;
  388. int n, do_gain, maxno = 0;
  389. //TW REVISED Dec 2002
  390. // char outfilename[256], *outfilenumber; /* RWD fname was only [64] */
  391. char outfilename[256];
  392. int numclipped = 0;
  393. double this_gain = 1.0, maxnoclip = 1.0;
  394. if((greater = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
  395. sprintf(errstr,"Insufficient memory to store file maxima\n");
  396. return(MEMORY_ERROR);
  397. }
  398. if(dz->true_outfile_stype == SAMP_FLOAT)
  399. if(dz->clip_floatsams == 0)
  400. clipsamps = 0;
  401. fprintf(stdout,"INFO: Finding loudest file\n");
  402. fflush(stdout);
  403. for(n=0;n<dz->infilecnt;n++) {
  404. maxfound = 0.0;
  405. dz->ifd[0] = dz->ifd[n];
  406. dz->total_samps_written = 0;
  407. dz->samps_left = dz->insams[n];
  408. dz->total_samps_read = 0;
  409. if((exit_status = find_max(&maxfound,dz))<0) {
  410. dz->ifd[0] = orig_ifd;
  411. return(exit_status);
  412. }
  413. if(maxfound > greatest) {
  414. greatest = maxfound;
  415. maxno = n;
  416. }
  417. greater[n] = maxfound/F_MAXSAMP;
  418. }
  419. greatest /= F_MAXSAMP;
  420. dz->ifd[0] = orig_ifd;
  421. dbamp = 20 * log10(greatest); /*RWD*/
  422. if(dz->mode==LOUDNESS_LOUDEST) {
  423. fprintf(stdout,"INFO: loudest file is %s with level %lf (%.3f dB)\n",dz->wordstor[maxno],greatest,dbamp);
  424. fflush(stdout);
  425. return(FINISHED);
  426. }
  427. fprintf(stdout,"INFO: Equalising levels\n");
  428. fflush(stdout);
  429. for(n=0;n<dz->infilecnt;n++) {
  430. dz->ssampsread = 0;
  431. dz->total_samps_read = 0;
  432. dz->ifd[0] = dz->ifd[n];
  433. if(sndseekEx(dz->ifd[0],0L,0)<0) {
  434. sprintf(errstr,"sndseekEx() failed.\n");
  435. return(SYSTEM_ERROR);
  436. }
  437. dz->total_samps_written = 0;
  438. dz->samps_left = dz->insams[n];
  439. dz->total_samps_read = 0;
  440. if(!flteq(greatest,greater[n])) {
  441. this_gain = greatest/greater[n];
  442. maxnoclip = fabs((double)F_MAXSAMP/this_gain);
  443. do_gain = 1;
  444. } else {
  445. do_gain = 0;
  446. }
  447. if(n>0) {
  448. strcpy(outfilename,dz->wordstor[dz->infilecnt]);
  449. /* RWD 9:2001 the -1 is unsafe if outname is only one char! */
  450. //TW This is a sloom requirement,as standard sloom temp outfile name is 'cdptest0'
  451. // and temporary-file housekeeping requires files to be named cdptestN in numeric order of N
  452. // However, we can do it differently for cmdline case....
  453. if(sloom)
  454. insert_new_number_at_filename_end(outfilename,n,1);
  455. else
  456. insert_new_number_at_filename_end(outfilename,n,0);
  457. if((exit_status = create_sized_outfile(outfilename,dz))<0) {
  458. sprintf(errstr,"Cannot open output file %s\n", outfilename);
  459. dz->ifd[0] = orig_ifd;
  460. return(DATA_ERROR);
  461. }
  462. }
  463. while(dz->samps_left > 0) {
  464. if((exit_status = read_samps(dz->sampbuf[0],dz))<0) {
  465. sprintf(errstr,"Cannot read data from sndfile %d\n",n+1);
  466. dz->ifd[0] = orig_ifd;
  467. return(PROGRAM_ERROR);
  468. }
  469. if(do_gain)
  470. gain(dz->ssampsread,this_gain,maxnoclip,&numclipped,clipsamps,&peak_val,dz);
  471. if(dz->ssampsread > 0) {
  472. if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0) {
  473. dz->ifd[0] = orig_ifd;
  474. return(exit_status);
  475. }
  476. }
  477. }
  478. if(n < dz->infilecnt - 1) {
  479. if((exit_status = headwrite(dz->ofd,dz))<0) {
  480. dz->ifd[0] = orig_ifd;
  481. return(exit_status);
  482. }
  483. if((exit_status = reset_peak_finder(dz))<0)
  484. return(exit_status);
  485. if(sndcloseEx(dz->ofd) < 0) {
  486. fprintf(stdout,"WARNING: Can't close output soundfile %s\n",outfilename);
  487. fflush(stdout);
  488. }
  489. dz->ofd = -1;
  490. }
  491. }
  492. dz->ifd[0] = orig_ifd;
  493. /*RWD*/
  494. if(clipsamps && (numclipped > 0))
  495. sprintf(errstr, "WARNING: %d samples were clipped.\n", numclipped);
  496. dz->peak_fval = peak_val;
  497. /*will get written to header automatically*/
  498. return(FINISHED);
  499. }
  500. //TW NEW FUNCTION, updated for floatsams and new-style clipping detection
  501. /********************** GAINENV ***************************/
  502. int gainenv(int samples,int *last_total,double maxnoclip,int *numclipped,int do_clip,double *peak,dataptr dz)
  503. {
  504. int exit_status;
  505. register int i;
  506. double s, buf_peak = *peak;
  507. double timeincr = 1.0/(double)dz->infile->srate;
  508. float *buffer = dz->sampbuf[0];
  509. double time = (double)(*last_total/dz->infile->channels)/(double)dz->infile->srate;
  510. for(i = 0; i < samples; i++) {
  511. if(i % dz->infile->channels == 0) {
  512. if((exit_status = read_value_from_brktable(time,LOUD_GAIN,dz))<0)
  513. return(exit_status);
  514. time += timeincr;
  515. }
  516. s = buffer[i];
  517. s *= dz->param[LOUD_GAIN];
  518. if(s >= 0) {
  519. if(do_clip && (s > maxnoclip)) {
  520. (*numclipped)++;
  521. s = 1.0;
  522. }
  523. buf_peak = max(buf_peak,s);
  524. } else {
  525. if(do_clip && (s < -maxnoclip)) {
  526. (*numclipped)++;
  527. s = -1.0;
  528. }
  529. buf_peak = max(buf_peak,-s);
  530. }
  531. buffer[i] = (float)s;
  532. }
  533. *peak = buf_peak;
  534. *last_total = dz->total_samps_read;
  535. return(FINISHED);
  536. }