Answers.Body: <p>I'm not really sure what the question is here, but I'll have a go at addressing some of the behaviours and error messages.</p>
  <p>According to the documentation of seewave::savewav savewav will normalize by default. I suspect setting rescale=null, as you have done, results in savewav following the default behaviour of normalising prior to writing, even though such syntax could be easily confused with 'not normalising' which seems to be what you were hoping would happen.</p>
  <p>If you prefer using savewav, you can get identical results to writeWave (including the warning message about rounding) by setting:</p>
  <p><code>rescale=c(min(FBD@left),max(FBD@left))</code></p>
  <p>Regarding the warning message:</p>
  <blockquote>
  <p>In writeWave...: channels' data will be rounded to integers for writing the wave file</p>
  </blockquote>
  <p>The bwfilter function is returning a vector of floating point numbers to give a very precise answer. However, writeWave is expecting integer data, so the function appears to be rounding the floating point values to the nearest integer. In my view this warning can be safely ignored and the fractional values aren't likely to be important here.</p>
  <p>As for the error message:</p>
  <blockquote>
  <p>In writeWave...:for 16-bit Wave files, data range is supposed to be in [-32768, 32767], see ?normalize</p>
  </blockquote>
  <p>This seems like a potential bug in writeWav in that it will happily read wav files that have values at the limits of the bit-depth, but it won't write them. I think the correct solution here would be to follow up with the developer of tuneR::writeWave. But a potential workaround here would be to check whether any of the data to be written exceeds or equals the data range, and set these to be one less than the lower or upper limits as appropriate (-32767,32766).</p>
  <p>I've modified your code to illustrate the various methods:</p>
  <pre><code>pathName &lt;- 'w:/LongTermRecording2002_present/Casey2014/'
  fileName &lt;- '200_2013-12-25_02-00-00.wav'
  short_name &lt;- tools::file_path_sans_ext(fileName)
  seewaveName &lt;- paste0(short_name,&quot;seewave_filtered250.wav&quot;)
  writewaveName &lt;- paste0(short_name,&quot;writewave_filtered250.wav&quot;)
  x = tuneR::readWave(filename = paste0(pathName,fileName))
  
  FBD &lt;- seewave::bwfilter(x, from = 0, to = 250,
                           bandpass = NULL, output = &quot;Wave&quot;)
  seewave::savewav(FBD, f=x@samp.rate, channel = 1, filename = seewaveName,
                   rescale=c(min(FBD@left),max(FBD@left)))
  tuneR::writeWave(FBD, filename=writewaveName)
  xSeewave &lt;- tuneR::readWave(filename = seewaveName)
  xWritewave &lt;- tuneR::readWave(filename = writewaveName)
  par(mfrow=c(3,1))
  plot(FBD)
  plot(xSeewave)
  plot(xWritewave)
  </code></pre>
  <p><a href="https://i.sstatic.net/YqKdq.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/YqKdq.png" alt="Plot of results" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-09-12T04:32:59.263Z
Answers.LastActivityDate: 2023-09-12T04:32:59.263Z
Answers.UserDisplayName: Brian Miller
Body: <p>I am currently working on a project where I would like to read in an audio file, apply a butterworth filter, and then export the filtered audio file while preserving the scale of the amplitude from the original audio file.</p>
  <p>I attempted to do this within the seewave and tuneR packages in R using this code:</p>
  <pre><code>BD &lt;- readWave(file_name)
  short_name &lt;- tools::file_path_sans_ext(file_name)
  FBD &lt;- bwfilter(BD, from = 0, to = 250, bandpass = NULL, output = &quot;Wave&quot;)
  savewav(FBD, f=24000, channel = 1, filename = paste0(short_name,&quot;_filtered250.wav&quot;), rescale=NULL)
  </code></pre>
  <p>I noticed with this code that when viewing the spectrograms and waveforms of the output files compared to the original audio files, that quiet files are getting rescaled significantly (to be much louder than the original file) while loud files are getting rescaled very little. I tested the code without the bwfilter function and found that simply reading the file in and then saving the output with the savewav function from seewave was still causing the same problem. I dug into the rescale argument in savewav and found that NULL normalizes the amplitude to default settings of the package instead of not rescaling at all, and it relies on the normalize function from tuneR.</p>
  <p>I then tested with this code to see if I could solve my problem:</p>
  <pre><code>  BD &lt;- readWave(file_name)
    short_name &lt;- tools::file_path_sans_ext(file_name)
    normalize(BD, unit = &quot;16&quot;, center = TRUE, level = 1, rescale = FALSE, pcm = BD@pcm) 
    savewav(BD, f=24000, channel = 1, filename=paste0(short_name,&quot;_rescaleNULLnormalizeFALSE.wav&quot;), rescale=NULL)
  </code></pre>
  <p>This attempt also scaled up the amplitude (see image below of original .wav file on left and output audio file on right).
  <a href="https://i.sstatic.net/CBygp.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/CBygp.png" alt="example of original .wav file compared to output .wav file from this attempt" /></a></p>
  <p>Next, instead of the savewav function, I used this alternate writeWave function:</p>
  <pre><code>BD &lt;- readWave(file_name)
  short_name &lt;- tools::file_path_sans_ext(file_name)
  writeWave(BD, filename=paste0(short_name,&quot;_writeWave.wav&quot;))
  </code></pre>
  <p>This attempt worked and produced audio files that did not rescale amplitude for quiet, moderate, and loud files. However, when I attempted to add back in the bwfilter function, I received warnings on all of my quiet and moderate files, and an error on the loud file.</p>
  <pre><code> BD &lt;- readWave(file_name)
   short_name &lt;- tools::file_path_sans_ext(file_name)
   FBD &lt;- bwfilter(BD, from = 0, to = 250, bandpass = NULL, output = &quot;Wave&quot;)
   writeWave(FBD, filename=paste0(short_name,&quot;_filter0bpNULLwriteWave.wav&quot;))
  </code></pre>
  <p>The warning messages for all the moderate/quiet files were saying <em><strong>in writeWave...: channels' data will be rounded to integers for writing the wave file</strong></em>
  The output .wav files from this attempt appear to have filtered correctly and the amplitude does not look like it has been rescaled.</p>
  <p>The error message for the large file was <em><strong>in writeWave...:for 16-bit Wave files, data range is supposed to be in [-32768, 32767], see ?normalize</strong></em>
  The loud audio file had a lot of clipping in it from high wind, but I do not understand why the writeWav function worked for the large file before, but not now when I attempt to filter it.</p>
  <p>Any advice on how to tackle this problem or alternate code suggestions would be greatly appreciated!</p>
  
Tags: <r><wav><filter><amplitude>
Title: How to preserve amplitude scale from original .wav audio file to output .wav file in seewave and tuneR packages after filtering
ThreadText: # How to preserve amplitude scale from original .wav audio file to output .wav file in seewave and tuneR packages after filtering
  
  (Asked by: username_0 on 2023-09-11)
  
  I am currently working on a project where I would like to read in an audio file, apply a butterworth filter, and then export the filtered audio file while preserving the scale of the amplitude from the original audio file.
  I attempted to do this within the seewave and tuneR packages in R using this code:
  BD <- readWave(file_name)
  short_name <- tools::file_path_sans_ext(file_name)
  FBD <- bwfilter(BD, from = 0, to = 250, bandpass = NULL, output = "Wave")
  savewav(FBD, f=24000, channel = 1, filename = paste0(short_name,"_filtered250.wav"), rescale=NULL)
  
  I noticed with this code that when viewing the spectrograms and waveforms of the output files compared to the original audio files, that quiet files are getting rescaled significantly (to be much louder than the original file) while loud files are getting rescaled very little. I tested the code without the bwfilter function and found that simply reading the file in and then saving the output with the savewav function from seewave was still causing the same problem. I dug into the rescale argument in savewav and found that NULL normalizes the amplitude to default settings of the package instead of not rescaling at all, and it relies on the normalize function from tuneR.
  I then tested with this code to see if I could solve my problem:
    BD <- readWave(file_name)
    short_name <- tools::file_path_sans_ext(file_name)
    normalize(BD, unit = "16", center = TRUE, level = 1, rescale = FALSE, pcm = BD@pcm) 
    savewav(BD, f=24000, channel = 1, filename=paste0(short_name,"_rescaleNULLnormalizeFALSE.wav"), rescale=NULL)
  
  This attempt also scaled up the amplitude (see image below of original .wav file on left and output audio file on right).
  
  Next, instead of the savewav function, I used this alternate writeWave function:
  BD <- readWave(file_name)
  short_name <- tools::file_path_sans_ext(file_name)
  writeWave(BD, filename=paste0(short_name,"_writeWave.wav"))
  
  This attempt worked and produced audio files that did not rescale amplitude for quiet, moderate, and loud files. However, when I attempted to add back in the bwfilter function, I received warnings on all of my quiet and moderate files, and an error on the loud file.
   BD <- readWave(file_name)
   short_name <- tools::file_path_sans_ext(file_name)
   FBD <- bwfilter(BD, from = 0, to = 250, bandpass = NULL, output = "Wave")
   writeWave(FBD, filename=paste0(short_name,"_filter0bpNULLwriteWave.wav"))
  
  The warning messages for all the moderate/quiet files were saying in writeWave...: channels' data will be rounded to integers for writing the wave file
  The output .wav files from this attempt appear to have filtered correctly and the amplitude does not look like it has been rescaled.
  The error message for the large file was in writeWave...:for 16-bit Wave files, data range is supposed to be in [-32768, 32767], see ?normalize
  The loud audio file had a lot of clipping in it from high wind, but I do not understand why the writeWav function worked for the large file before, but not now when I attempt to filter it.
  Any advice on how to tackle this problem or alternate code suggestions would be greatly appreciated!
  
  **Tags:** r, wav, filter, amplitude
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2023-09-12. Score: 2
  
  I'm not really sure what the question is here, but I'll have a go at addressing some of the behaviours and error messages.
  According to the documentation of seewave::savewav savewav will normalize by default. I suspect setting rescale=null, as you have done, results in savewav following the default behaviour of normalising prior to writing, even though such syntax could be easily confused with 'not normalising' which seems to be what you were hoping would happen.
  If you prefer using savewav, you can get identical results to writeWave (including the warning message about rounding) by setting:
  rescale=c(min(FBD@left),max(FBD@left))
  Regarding the warning message:
  
  In writeWave...: channels' data will be rounded to integers for writing the wave file
  
  The bwfilter function is returning a vector of floating point numbers to give a very precise answer. However, writeWave is expecting integer data, so the function appears to be rounding the floating point values to the nearest integer. In my view this warning can be safely ignored and the fractional values aren't likely to be important here.
  As for the error message:
  
  In writeWave...:for 16-bit Wave files, data range is supposed to be in [-32768, 32767], see ?normalize
  
  This seems like a potential bug in writeWav in that it will happily read wav files that have values at the limits of the bit-depth, but it won't write them. I think the correct solution here would be to follow up with the developer of tuneR::writeWave. But a potential workaround here would be to check whether any of the data to be written exceeds or equals the data range, and set these to be one less than the lower or upper limits as appropriate (-32767,32766).
  I've modified your code to illustrate the various methods:
  pathName <- 'w:/LongTermRecording2002_present/Casey2014/'
  fileName <- '200_2013-12-25_02-00-00.wav'
  short_name <- tools::file_path_sans_ext(fileName)
  seewaveName <- paste0(short_name,"seewave_filtered250.wav")
  writewaveName <- paste0(short_name,"writewave_filtered250.wav")
  x = tuneR::readWave(filename = paste0(pathName,fileName))
  
  FBD <- seewave::bwfilter(x, from = 0, to = 250,
                           bandpass = NULL, output = "Wave")
  seewave::savewav(FBD, f=x@samp.rate, channel = 1, filename = seewaveName,
                   rescale=c(min(FBD@left),max(FBD@left)))
  tuneR::writeWave(FBD, filename=writewaveName)
  xSeewave <- tuneR::readWave(filename = seewaveName)
  xWritewave <- tuneR::readWave(filename = writewaveName)
  par(mfrow=c(3,1))
  plot(FBD)
  plot(xSeewave)
  plot(xWritewave)
  
  
  ---
  
  