COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :

Go Back   Cockos Incorporated Forums > Other Software Discussion > WDL users forum

Reply
 
Thread Tools Display Modes
Old 09-19-2017, 06:23 PM   #1
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default Where have I gone wrong with this Peak/RMS code?

Flummoxed by this at the moment! I'm trying to get a Peak/RMS meter going, but it's giving strange results. I'm comparing the output with RMSBuddy and Voxengo Span which both give the same output, but can't get mine to match.

This code is giving me different results everywhere. In Ableton Live on OSX the RMS is about 3db below expected but goes higher and out of range if I increase Ableton's buffer size, and in Logic the RMS comes out around 1db lower than it should, but changing the buffer size didn't seem to affect it. Absolute Peak and Continuous Peak are coming through as expected in both. Using Ableton in Windows gives me both Peak and RMS of about 1300db :-/

Here's the troublesome code:

Code:
     int peakRMSWindowLength, peakRMSWindowCounter;
     double aveRMS, contRMS, absPeak, contPeak, allSamplesReceived;
     unsigned long totalSamples;

void IPlugEffect::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
     // Mutex is already locked for us.
     
     double* in1 = inputs[0];
     double* in2 = inputs[1];
     double* out1 = outputs[0];
     double* out2 = outputs[1];
     
     // Reset parameters if playback is initiated after playback was stopped
     ITimeInfo ti;
     GetTime(&ti);
     bool isPlaying = ti.mTransportIsRunning;
     if (!m_WasPlaying && isPlaying) {
          allSamplesReceived = 0.0;
          totalSamples = 0;
          peakRMSWindowCounter = 0;
          contPeak = 0.0;
          contRMS = 0.0;
     }
     m_WasPlaying = isPlaying;
     
     // Processing loop
     for (int s = 0; s < nFrames; ++s, ++in1, ++in2, ++out1, ++out2)
     {
          // Increment Peak/RMS Counters
          totalSamples++;
          peakRMSWindowCounter++;
          
          // Square the input and add to the stored values
          double inSquared = in1[s] * in1[s];
          contRMS += inSquared;
          allSamplesReceived += inSquared;
          
          // Update the absolute peak value if the continuous value is higher than the stored value
          if (inSquared > contPeak)
               contPeak = inSquared;
          
          // Output text
          char text[200];
          sprintf(text, "total = %i, peakRMSWindowCounter = %i, windowlength = %i, bufsize = %i", (int)totalSamples, peakRMSWindowCounter, peakRMSWindowLength, nFrames);
          pTextOut->SetTextFromPlug(text);
          
          // Update the Peak/RMS values if the window length has been reached
          if (peakRMSWindowCounter >= peakRMSWindowLength) {
               
               // unsquare the results to get the actual sample value
               contPeak = sqrt(contPeak);
               aveRMS = sqrt(allSamplesReceived / (double)(totalSamples));
               contRMS = sqrt(contRMS / (double)peakRMSWindowLength);
               
               // Check if the Continuous Peak was higher than the Absolute Peak
               if (contPeak > absPeak)
                    absPeak = contPeak;
               
               // Send new values to display meters
               pAverageRMSOutputR->SetValue(ConvertSampleToDB(aveRMS));
               pContRMSOutputR->SetValue(ConvertSampleToDB(contRMS));
               pAbsolutePeakOutputR->SetValue(ConvertSampleToDB(absPeak));
               pContPeakOutputR->SetValue(ConvertSampleToDB(contPeak));
               
               peakRMSWindowCounter = 0;
               contPeak = 0.0;
               contRMS = 0.0;
          }
          
          *out1 = *in1;
          *out2 = *in2;
     } // End of processing loop
Bobflip is offline   Reply With Quote
Old 09-19-2017, 06:40 PM   #2
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Oh yeah, and I have the window length set this way - i is the output of a control knob, it's giving 44100 for a 1 second window setting at 44.1khz, so that seems ok!

peakRMSWindowLength = ConvertMSToSamples(i, mSampleRate);

inline double ConvertMSToSamples(double in, double sampleRate) {
return in * sampleRate * 0.001;
}
Bobflip is offline   Reply With Quote
Old 09-19-2017, 11:40 PM   #3
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,652
Default

Quote:
Originally Posted by Bobflip View Post
Code:
     for (int s = 0; s < nFrames; ++s, ++in1, ++in2, ++out1, ++out2)
     {
          ...
          double inSquared = in1[s] * in1[s];
This can't be right, because you are incrementing both s and in1 in your for statement.
Tale is offline   Reply With Quote
Old 09-20-2017, 04:52 AM   #4
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Gaaahh! Hahaha, that's solved it. Well spotted, thanks :-)
I could tell the buffer size was coming into play but couldn't work out where.

I had been adding the code to the IPlugEffect example and used in1[s] * in1[s] instead of *in1 * *in1.


Is there any advantage to using *in1 over in1[s]?
Bobflip is offline   Reply With Quote
Old 09-20-2017, 06:57 AM   #5
Tale
Human being with feelings
 
Tale's Avatar
 
Join Date: Jul 2008
Location: The Netherlands
Posts: 3,652
Default

Quote:
Originally Posted by Bobflip View Post
Is there any advantage to using *in1 over in1[s]?
I guess this depends heavily on your compiler and settings, but with full optimizations your compiler will probably generate almost the same code anyway, so there is is no real advantage.

That being said, if you have a very tight loop (not too much code, only a few variables), then using pointers will likely be slightly more efficient. However, for loops with a lot of code inside, like ProcessDoubleReplacing(), it is likely that removing the pointers altogether (i.e. let your compiler decide) will be more efficient.
Tale is offline   Reply With Quote
Old 09-20-2017, 07:03 AM   #6
Bobflip
Human being with feelings
 
Join Date: Nov 2016
Posts: 341
Default

Cool, thanks for that! I'd been thinking they were pretty much interchangeable but the extra info there makes sense. I need to learn about compiler optimisations soon so will bear that in mind.
Bobflip is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 11:47 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.