From dbf79e1d1ebf4276815d1bf382d52443aa23ca99 Mon Sep 17 00:00:00 2001 From: boblark Date: Fri, 19 Jun 2020 20:31:56 -0700 Subject: [PATCH] Correct for T4, add peak, rms, Gaussian --- AudioMixer_F32.cpp | 7 +- OpenAudio_ArduinoLibrary.h | 8 +- analyze_peak_f32.cpp | 90 +++++++++++++++ analyze_peak_f32.h | 103 +++++++++++++++++ analyze_rms_f32.cpp | 68 ++++++++++++ analyze_rms_f32.h | 105 ++++++++++++++++++ ...c3206.cpp => control_tlv320aic3206.cpp.xxx | 0 ...20aic3206.h => control_tlv320aic3206.h.xxx | 0 .../SignalNoise_float/SignalNoise_float.ino | 103 +++++++++++++++++ input_i2s_f32.cpp => input_i2s_f32.cpp.xxx | 0 input_i2s_f32.h => input_i2s_f32.h.xxx | 0 output_i2s_f32.cpp => output_i2s_f32.cpp.xxx | 0 output_i2s_f32.h => output_i2s_f32.h.xxx | 0 readme.md | 11 +- synth_GaussianWhiteNoise_F32.cpp | 95 ++++++++++++++++ synth_GaussianWhiteNoise_F32.h | 76 +++++++++++++ ...ise_f32.cpp.xxx => synth_pinknoise_f32.cpp | 13 ++- ...nknoise_f32.h.xxx => synth_pinknoise_f32.h | 6 +- synth_sine_f32.cpp | 10 +- synth_sine_f32.h | 3 - synth_whitenoise_f32.cpp | 7 +- 21 files changed, 679 insertions(+), 26 deletions(-) create mode 100644 analyze_peak_f32.cpp create mode 100644 analyze_peak_f32.h create mode 100644 analyze_rms_f32.cpp create mode 100644 analyze_rms_f32.h rename control_tlv320aic3206.cpp => control_tlv320aic3206.cpp.xxx (100%) rename control_tlv320aic3206.h => control_tlv320aic3206.h.xxx (100%) create mode 100644 examples/SignalNoise_float/SignalNoise_float.ino rename input_i2s_f32.cpp => input_i2s_f32.cpp.xxx (100%) rename input_i2s_f32.h => input_i2s_f32.h.xxx (100%) rename output_i2s_f32.cpp => output_i2s_f32.cpp.xxx (100%) rename output_i2s_f32.h => output_i2s_f32.h.xxx (100%) create mode 100644 synth_GaussianWhiteNoise_F32.cpp create mode 100644 synth_GaussianWhiteNoise_F32.h rename synth_pinknoise_f32.cpp.xxx => synth_pinknoise_f32.cpp (96%) rename synth_pinknoise_f32.h.xxx => synth_pinknoise_f32.h (97%) diff --git a/AudioMixer_F32.cpp b/AudioMixer_F32.cpp index 092b3f7..5c644f8 100644 --- a/AudioMixer_F32.cpp +++ b/AudioMixer_F32.cpp @@ -1,3 +1,6 @@ +// Fix 1 to n problem Bob Larkin June 2020 +// Need to convert to TYmpan routine?? + #include "AudioMixer_F32.h" void AudioMixer4_F32::update(void) { @@ -8,7 +11,7 @@ void AudioMixer4_F32::update(void) { arm_scale_f32(out->data, multiplier[0], out->data, out->length); - for (int channel=1; channel < 4; channel++) { + for (int channel=0; channel < 4; channel++) { // Was 1 to 3 RSL June 2020 in = receiveReadOnly_f32(channel); if (!in) { continue; @@ -38,7 +41,7 @@ void AudioMixer8_F32::update(void) { arm_scale_f32(out->data, multiplier[0], out->data, out->length); //scale the first input channel //load and process the rest of the channels - for (int channel=1; channel < 8; channel++) { + for (int channel=0; channel < 8; channel++) { // Was 1 to 7 RSL June 2020 in = receiveReadOnly_f32(channel); if (!in) { continue; diff --git a/OpenAudio_ArduinoLibrary.h b/OpenAudio_ArduinoLibrary.h index b5af6e1..f432507 100644 --- a/OpenAudio_ArduinoLibrary.h +++ b/OpenAudio_ArduinoLibrary.h @@ -17,11 +17,15 @@ #include "AudioMixer_F32.h" #include "AudioMultiply_F32.h" #include "AudioSettings_F32.h" -#include "input_i2s_f32.h" -#include "output_i2s_f32.h" +// #include "input_i2s_f32.h" needs fixing, set to .xxx +// #include "output_i2s_f32.h" needs fixing, set to .xxx #include "play_queue_f32.h" #include "record_queue_f32.h" #include "synth_pinknoise_f32.h" #include "synth_sine_f32.h" #include "synth_waveform_F32.h" #include "synth_whitenoise_f32.h" +#include "synth_GaussianWhiteNoise_F32.h" +#include "analyze_peak_f32.h" +#include "analyze_rms_f32.h" +// #include "control_tlv320aic3206.h" collides much with Teensy Audio diff --git a/analyze_peak_f32.cpp b/analyze_peak_f32.cpp new file mode 100644 index 0000000..ed635b1 --- /dev/null +++ b/analyze_peak_f32.cpp @@ -0,0 +1,90 @@ +/* + * This is a direct translation of the Teensy Audio Library Peak Analyze + * to use floating point f32. This is intended to be compatible with + * Chip Audette's floating point libraries. + * Bob Larkin 23 April 2020 - AudioAnalyze_Peak_F32 + * + * Regard the Paul Stoffregen copyright and licensing: + * + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "AudioStream_F32.h" +#include "analyze_peak_f32.h" + +void AudioAnalyzePeak_F32::update(void) { + audio_block_f32_t *blockIn; + const float32_t *p, *end; + float32_t min, max, d; + + blockIn = AudioStream_F32::receiveReadOnly_f32(); + if (!blockIn) { + if(errorPrint) Serial.println("AN_PEAK ERR: No input memory"); + return; + } + + // Variable just_read allows both read() and readPeakToPeak() to be used + if(just_read) { + // Start new collection of min_sample and max_sample + min_sample = blockIn->data[0]; + max_sample = blockIn->data[0]; + } + + p = blockIn->data; + end = p + block_size; + min = min_sample; + max = max_sample; + do { + d=*p++; + if (dmax) max=d; + } while (p < end); + min_sample = min; + max_sample = max; + new_output = true; // Tell available() that data is available + AudioStream_F32::release(blockIn); + } + +float AudioAnalyzePeak_F32::read(void) { + // Tell update to start new + just_read = true; + __disable_irq(); + float32_t min = min_sample; + float32_t max = max_sample; + __enable_irq(); + min = abs(min); + max = abs(max); + if (min > max) max = min; + return max; + } + +float AudioAnalyzePeak_F32:: readPeakToPeak(void) { + just_read = true; + __disable_irq(); + float32_t min = min_sample; + float32_t max = max_sample; + __enable_irq(); + return (max - min); + } diff --git a/analyze_peak_f32.h b/analyze_peak_f32.h new file mode 100644 index 0000000..494f9d8 --- /dev/null +++ b/analyze_peak_f32.h @@ -0,0 +1,103 @@ +/* This is a direct translation of the Teensy Audio Library Peak Analyze + * to use floating point f32. This is intended to be compatible with + * Chip Audette's floating point libraries. + * Bob Larkin 24 April 2020 - AudioAnalyze_Peak_F32 + * + * Regard the copyright and the licensing: + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + /* Input is a block of f32 numbers. Output is the peak signal amplitude + * calculated over multiple blocks. Useful for audio level response projects, + * and general troubleshooting. + * + * Status: Tested 3.6 and 4.0, no known bugs + * Functions: + * available(); Returns true if new peak data is available. + * read(); Read the new peak value. + * Return is absolute + or - peak value in float. + * readPeakToPeak(); Same, but the differnce in + and - values. + * Examples: + * TestPeakRMS.ino + * Similar: File > Examples > Audio > Analysis > PeakAndRMSMeterStereo + * Time: Measured Teensy 3.6 time for the update() is 10 microseconds, + * for 128 block size. For Teensy 4.0 this is about 4 mcroseconds. + * + * The two variables, min_sample and max_sample, are checked until + * an available() takes place. This is fine if the statistics of the input data are + * stationary, i.e., not changing with time. But, if the process is not + * stationary, be aware and do available() & read() at appropriate times. + */ + +#ifndef analyze_peak_f32_h_ +#define analyze_peak_f32_h_ + +#include "Arduino.h" +#include "AudioStream_F32.h" + +class AudioAnalyzePeak_F32 : public AudioStream_F32 { +//GUI: inputs:1, outputs:0 //this line used for automatic generation of GUI node +//GUI: shortName: AnalyzePeak +public: + AudioAnalyzePeak_F32(void) : AudioStream_F32(1, inputQueueArray_f32) { + } + // Alternate specification of block size. Sample rate does not apply for analyze_peak + AudioAnalyzePeak_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32) { + block_size = settings.audio_block_samples; + } + + bool available(void) { // true means read() or readPeakToPeak() will return a new value + __disable_irq(); + bool flag = new_output; + if (flag) new_output = false; + __enable_irq(); + return flag; + } + + void showError(uint16_t e) { // 0/1 Disables/Enables printing of update() errors + errorPrint = e; + } + + virtual void update(void); + float32_t read(void); + float32_t readPeakToPeak(void); + +private: + audio_block_f32_t *inputQueueArray_f32[1]; + uint16_t block_size = AUDIO_BLOCK_SAMPLES; + volatile bool new_output = false; + volatile bool just_read = true; + float32_t min_sample; + float32_t max_sample; + + // Control error printing in update(). Should never be enabled + // until all audio objects have been initialized. + // Only used as 0 or 1 now, but 16 bits are available. + uint16_t errorPrint = 0; +}; +#endif + + diff --git a/analyze_rms_f32.cpp b/analyze_rms_f32.cpp new file mode 100644 index 0000000..5890cc0 --- /dev/null +++ b/analyze_rms_f32.cpp @@ -0,0 +1,68 @@ +/* + * This is a direct translation of the Teensy Audio Library RMS Analyze + * to use floating point f32. This is intended to be compatible with + * Chip Audette's floating point libraries. + * Bob Larkin 23 April 2020 - AudioAnalyze_RMS_F32 + * + * Regard the Paul Stoffregen copyright and licensing: + * + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "AudioStream_F32.h" +#include "analyze_rms_f32.h" + +void AudioAnalyzeRMS_F32::update(void) { + float32_t *p; + float32_t sum = 0.0f; + audio_block_f32_t *blockIn; + + blockIn = AudioStream_F32::receiveReadOnly_f32(); + if (!blockIn) { + if(errorPrint) Serial.println("AN_RMS ERR: No input"); + // count++; // Why ++? We are not adding to accum + return; + } + + p = blockIn->data; + // Find sum of powers for full vector, see + // https://github.com/ARM-software/CMSIS/blob/master/CMSIS/DSP_Lib/Source/BasicMathFunctions/arm_dot_prod_f32.c + // arguments are (source vector 1, source vector 2, number of samples, pointer to f32 out) + arm_dot_prod_f32(p, p, block_size, &sum); + accum += (double)sum; + count++; + AudioStream_F32::release(blockIn); +} + +float AudioAnalyzeRMS_F32::read(void) { + __disable_irq(); + // It is safe to convert back to float now + float32_t sum = (float32_t)accum; + accum = 0.0; + float32_t num = (float32_t)count; + count = 0; + __enable_irq(); + return sqrtf(sum / (num * (float32_t)block_size)); +} diff --git a/analyze_rms_f32.h b/analyze_rms_f32.h new file mode 100644 index 0000000..7c9551c --- /dev/null +++ b/analyze_rms_f32.h @@ -0,0 +1,105 @@ +/* This is a direct translation of the Teensy Audio Library RMS Analyze + * to use floating point f32. This is intended to be compatible with + * Chip Audette's floating point libraries. + * Bob Larkin 23 April 2020 - AudioAnalyze_RMS_F32 + * + * Regard the copyright and licensing: + * Audio Library for Teensy 3.X + * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com + * + * Development of this audio library was funded by PJRC.COM, LLC by sales of + * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop + * open source software by purchasing Teensy or other PJRC products. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + /* Input is a block of f32 numbers. Output is the signal RMS amplitude + * calculated over multiple blocks. Useful for audio level response projects, + * and general troubleshooting. + * + * Status: Tested 3.6 and T4.0 No known bugs. + * Functions: + * available(); Returns true if new RMS data is available. + * read(); Read the new RMS value. Return is rms value in float. + * Examples: + * TestPeakRMS.ino + * Similar: File > Examples > Audio > Analysis > PeakAndRMSMeterStereo + * Time: Measured time for the update of F32 RMS is 7 microseconds + * for 128 block size. + * + * The average "power" is found by squaring the sample values, adding them + * together and dividing by the number of samples. The RMS value is a "voltage" + * found by taking the square root of the power. This is in DSP lingo, and + * the units are vague. But, since usually, only relative values are important, + * the units will cancel out! + * + * The two variables, accum and count, keep adding to the power sum until + * a read() takes place. This is fine if the statistics of the input data are + * stationary, i.e., not changing with time. But, if the process is not + * stationary, be aware and do read() at appropriate times. + */ + +#ifndef analyze_rms_f32_h_ +#define analyze_rms_f32_h_ + +#include "Arduino.h" +#include "AudioStream_F32.h" + +class AudioAnalyzeRMS_F32 : public AudioStream_F32 { +//GUI: inputs:1, outputs:0 //this line used for automatic generation of GUI node +//GUI: shortName: AnalyzeRMS +public: + AudioAnalyzeRMS_F32(void) : AudioStream_F32(1, inputQueueArray_f32) { + // default values from initialization below + } + // Alternate specification of block size. Sample rate does not apply for analyze_rms + AudioAnalyzeRMS_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32) { + block_size = settings.audio_block_samples; + } + + bool available(void) { + return count > 0; + } + + void showError(uint16_t e) { // 0/1 Disables/Enables printing of update() errors + errorPrint = e; + } + + float read(void); + + virtual void update(void); + +private: + audio_block_f32_t *inputQueueArray_f32[1]; + uint16_t block_size = AUDIO_BLOCK_SAMPLES; + // double for accum is very safe, but needed? Well, power dynamic Range x 1 sec of data =~ 1E7 x 4E4 = 4E11 + // whereas float range for positive numbers is 2^23 =~ 1E7 so double is easily justified for accuracy. + // The timing 7 microseconds per 128, includes using double for accum, so the price is reasonable. + double accum = 0.0; + uint32_t count = 0; + + // Control error printing in update(). Should never be enabled + // until all audio objects have been initialized. + // Only used as 0 or 1 now, but 16 bits are available. + uint16_t errorPrint = 0; +}; +#endif + + diff --git a/control_tlv320aic3206.cpp b/control_tlv320aic3206.cpp.xxx similarity index 100% rename from control_tlv320aic3206.cpp rename to control_tlv320aic3206.cpp.xxx diff --git a/control_tlv320aic3206.h b/control_tlv320aic3206.h.xxx similarity index 100% rename from control_tlv320aic3206.h rename to control_tlv320aic3206.h.xxx diff --git a/examples/SignalNoise_float/SignalNoise_float.ino b/examples/SignalNoise_float/SignalNoise_float.ino new file mode 100644 index 0000000..05a1122 --- /dev/null +++ b/examples/SignalNoise_float/SignalNoise_float.ino @@ -0,0 +1,103 @@ +/* SignalNoise_float.ino Bob Larkin 19 June 2020 + * + * Generate White Noise, Pink Noise, Gaussian White Noise and a Sine Wave + * Combine all four in a adding "mixer", send to Codec and to peak/rms. + * + * Following is for all objects enabled (amplitudes non-zero) + * T3.6 Processor load, measured: 10.6% + * T4.0 Processor load, measured: 3.2% + */ + +#include "Audio.h" +#include "OpenAudio_ArduinoLibrary.h" + +// To work with T4.0 the I2S routine outputs 16-bit integer (I16). Then +// use Audette I16 to F32 convert. Same below for output, in reverse. +AudioInputI2S in1; +AudioSynthNoisePink_F32 pink1; +AudioSynthNoiseWhite_F32 white1; +AudioSynthGaussian_F32 gaussian1; +AudioSynthWaveformSine_F32 sine1; +AudioMixer4_F32 sum1; +AudioConvert_F32toI16 cnvrt1; // Left +AudioConvert_F32toI16 cnvrt2; // Right +AudioOutputI2S i2sOut; +AudioAnalyzePeak_F32 peak1; +AudioAnalyzeRMS_F32 rms1; +AudioControlSGTL5000 codec; +AudioConnection_F32 connect1(pink1, 0, sum1, 0); +AudioConnection_F32 connect2(white1, 0, sum1, 1); +AudioConnection_F32 connect3(gaussian1, 0, sum1, 2); +AudioConnection_F32 connect4(sine1, 0, sum1, 3); +AudioConnection_F32 connect6(sum1, 0, cnvrt1, 0); // Out to the CODEC left +AudioConnection_F32 connect7(sum1, 0, cnvrt2, 0); // and right +AudioConnection_F32 connect8(sum1, 0, peak1, 0); +AudioConnection_F32 connect9(sum1, 0, rms1, 0); +AudioConnection conI16_2(cnvrt1, 0, i2sOut, 0); // DAC L +AudioConnection conI16_3(cnvrt2, 0, i2sOut, 1); // DAC R + + +// ********* Mini Control Panel ********* +// Off/On switches, 0 for off, 1 for on +#define WHITE 0 +#define PINK 0 +#define GAUSSIAN 1 +#define SINE 1 + +int gainControlDB = -35; // Set gain in dB. +// ***************************************** + +void setup(void) { + float32_t gain; + AudioMemory(5); + AudioMemory_F32(8); + + for (int i=0; i<4; i++) sum1.gain(i, 0.0); // All off + + Serial.begin(1); delay(1000); + + gain = powf( 10.0f, (gainControlDB/20.0f) ); + white1.amplitude(0.5f); + gaussian1.amplitude(0.5f); + sine1.frequency(1000.0f); + sine1.amplitude(0.2f); + codec.enable(); + delay(10); + if(PINK) sum1.gain(0, gain); + else sum1.gain(0, 0.0f); + + if(WHITE) sum1.gain(1, gain); + else sum1.gain(1, 0.0f); + + if(GAUSSIAN) sum1.gain(2, gain); + else sum1.gain(2, 0.0f); + + if(SINE) sum1.gain(3, gain); + else sum1.gain(3, 0.0f); +} + +void loop(void) { +// Here is where the adjustment of the volume control could go. +// And anything else that needs regular attention, other +// than the audio stream. + + if (rms1.available() ) {Serial.print("RMS ="); Serial.println(rms1.read(), 6);} + if (peak1.available() ) {Serial.print("P-P ="); Serial.println(peak1.readPeakToPeak(), 6);} + Serial.print("CPU: Percent Usage, Max: "); + Serial.print(AudioProcessorUsage()); + Serial.print(", "); + Serial.print(AudioProcessorUsageMax()); + Serial.print(" "); + Serial.print("Int16 Memory: "); + Serial.print(AudioMemoryUsage()); + Serial.print(", "); + Serial.print(AudioMemoryUsageMax()); + Serial.print(" "); + Serial.print("Float Memory: "); + Serial.print(AudioMemoryUsage_F32()); + Serial.print(", "); + Serial.println(AudioMemoryUsageMax_F32()); + Serial.println(); + + delay(1000); +} diff --git a/input_i2s_f32.cpp b/input_i2s_f32.cpp.xxx similarity index 100% rename from input_i2s_f32.cpp rename to input_i2s_f32.cpp.xxx diff --git a/input_i2s_f32.h b/input_i2s_f32.h.xxx similarity index 100% rename from input_i2s_f32.h rename to input_i2s_f32.h.xxx diff --git a/output_i2s_f32.cpp b/output_i2s_f32.cpp.xxx similarity index 100% rename from output_i2s_f32.cpp rename to output_i2s_f32.cpp.xxx diff --git a/output_i2s_f32.h b/output_i2s_f32.h.xxx similarity index 100% rename from output_i2s_f32.h rename to output_i2s_f32.h.xxx diff --git a/readme.md b/readme.md index 2f63a83..382e26b 100644 --- a/readme.md +++ b/readme.md @@ -4,8 +4,15 @@ OpenAudio Library for Teensy **Special Note** 17 June 2020 - This library is undergoing revision to make Teensy 4.x compatible and to add functionality. Changes are expected throughout the rest of June. See this readme for summaries during this period. Notes: 1-synth_sine_f32.h & .cpp allowed both KINETISK and__IMXRT1062__ to support T4.x. Tested 3.6, 4.0 -2-Hid synth_pinknoise_f32.h & .cpp with .xxx type. Allows T4 compile until these are fixed. -3-Fix synth_whitenoise_f32.cpp to include __IMXRT1062__ . +2-Fix synth_pinknoise_f32.h & .cpp built in I16 to F32. Now T3 and T4. +3-Fix synth_whitenoise_f32.cpp to include IMXRT1062 and built in I16 to F32. Now T3 and T4. +4-Added Gaussian White Noise F32. This is T3 and T4. +5-Renamed 3206 codec to .xxx to stop collisions with Teensy I16 library. Needs work. +6-Added new examples/SignalNoise_float.ino to test white, pink, Gaussian noise and sine. Audio out. +7-Disabled output_i2s_f32.h, .cpp by .xxxfile type. These need rework for T4. Use Convert_F32toI16. +8-Disabled control_tlv320aic3206.h, .cpp by .xxxfile type. These collide with Teensy I16 Audio. +9-Added new analyze_peak_f32.h and .cpp that parallel similar classes in the Teensy I16 library. +10-Added new analyze_rms_f32.h and .cpp that parallel similar classes in the Teensy I16 library. **Purpose**: The purpose of this library is to build upon the [Teensy Audio Library](http://www.pjrc.com/teensy/td_libs_Audio.html) to enable new functionality for real-time audio processing. diff --git a/synth_GaussianWhiteNoise_F32.cpp b/synth_GaussianWhiteNoise_F32.cpp new file mode 100644 index 0000000..e316820 --- /dev/null +++ b/synth_GaussianWhiteNoise_F32.cpp @@ -0,0 +1,95 @@ +/* + * synth_GaussianWhiteNoise_F32.cpp + * by Bob Larkin W7PUA 15 June 2020 + * + * Created: Chip Audette, OpenAudio, Feb 2017 + + + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice, development funding notice, and this permission + * notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "synth_GaussianWhiteNoise_F32.h" + +// Park-Miller-Carta Pseudo-Random Number Generator +// http://www.firstpr.com.au/dsp/rand31/ + +void AudioSynthGaussian_F32::update(void) +{ + audio_block_f32_t *blockOut; + uint32_t it; + float32_t rdev = 0.0f; + float32_t* pd; + + if (sd < 0.01f) { + return; // Not enabled + } + +#if TEST_TIME_GWN + if (iitt++ >1000000) iitt = -10; + uint32_t t1, t2; + t1 = tElapse; +#endif + blockOut = AudioStream_F32::allocate_f32(); + if (!blockOut) { + if(errorPrint) Serial.println("GWN-ERR: No output memory"); + return; + } + + pd = &blockOut->data[0]; // Pointer to write data + /* The "Even Quicker" uniform random sample generator from D. E. Knuth and + * H. W. Lewis and described in Chapter 7 of "Numerical Receipes in C", + * 2nd ed, with the comment "this is about as good as any 32-bit linear + * congruential generator, entirely adequate for many uses." + */ + for(int i=0; idata); //end = p + AUDIO_BLOCK_SAMPLES/2; end = p + (block_f32->length)/2; @@ -153,14 +155,15 @@ void AudioSynthNoisePink_F32::update(void) pdec = dec; paccu = accu; plfsr = lfsr; - + //convert int16 to f32 - AudioInputI2S_F32::convert_i16_to_f32(block->data,block_f32->data,block_f32->length); + #define I16_TO_F32_NORM_FACTOR (3.051757812500000E-05) //which is 1/32768 + for (int i=0; ilength; i++) + block_f32->data[i] = (float32_t)block->data[i] * I16_TO_F32_NORM_FACTOR; AudioStream_F32::transmit(block_f32); AudioStream_F32::release(block_f32); AudioStream::release(block); - } diff --git a/synth_pinknoise_f32.h.xxx b/synth_pinknoise_f32.h similarity index 97% rename from synth_pinknoise_f32.h.xxx rename to synth_pinknoise_f32.h index 0a9d624..8c8260d 100644 --- a/synth_pinknoise_f32.h.xxx +++ b/synth_pinknoise_f32.h @@ -65,7 +65,9 @@ public: level = (int32_t)(n * 65536.0); } virtual void update(void); - int enabled = 0; + + int enabled = 1; //0; + private: static const uint8_t pnmask[256]; static const int32_t pfira[64]; @@ -76,7 +78,7 @@ private: int32_t pdec; // decrement for all noise sources int32_t paccu; // accumulator uint8_t pncnt; // overflowing counter as index to pnmask[] - int32_t level; // 0=off, 65536=max + int32_t level=65536; // 0=off, 65536=max }; #endif diff --git a/synth_sine_f32.cpp b/synth_sine_f32.cpp index 6e7c2e1..adc2380 100644 --- a/synth_sine_f32.cpp +++ b/synth_sine_f32.cpp @@ -18,7 +18,6 @@ extern "C" { extern const int16_t AudioWaveformSine[257]; } - void AudioSynthWaveformSine_F32::update(void) { audio_block_f32_t *block; @@ -40,19 +39,16 @@ void AudioSynthWaveformSine_F32::update(void) scale = (ph >> 8) & 0xFFFF; val2 *= scale; val1 *= 0x10000 - scale; - #if defined(KINETISK) + #if (defined(KINETISK) || defined(__IMXRT1062__) ) block->data[i] = (float) multiply_32x32_rshift32(val1 + val2, magnitude); #elif defined(KINETISL) block->data[i] = (float) ((((val1 + val2) >> 16) * magnitude) >> 16); #endif - ph += inc; - + ph += inc; block->data[i] = block->data[i] / 32767.0f; // scale to float } phase_accumulator = ph; - - - + AudioStream_F32::transmit(block); AudioStream_F32::release(block); return; diff --git a/synth_sine_f32.h b/synth_sine_f32.h index 8d77d1b..a11025d 100644 --- a/synth_sine_f32.h +++ b/synth_sine_f32.h @@ -60,7 +60,4 @@ private: float sample_rate_Hz = AUDIO_SAMPLE_RATE; volatile uint8_t enabled = 1; }; - - - #endif diff --git a/synth_whitenoise_f32.cpp b/synth_whitenoise_f32.cpp index 401bd7e..97aef4a 100644 --- a/synth_whitenoise_f32.cpp +++ b/synth_whitenoise_f32.cpp @@ -33,7 +33,6 @@ */ #include "synth_whitenoise_f32.h" -#include "input_i2s_f32.h" //for the audio_convert_i16_to_f32 routine // Park-Miller-Carta Pseudo-Random Number Generator // http://www.firstpr.com.au/dsp/rand31/ @@ -111,9 +110,11 @@ void AudioSynthNoiseWhite_F32::update(void) #endif } while (p < end); seed = lo; - + //convert int16 to f32 - AudioInputI2S_F32::convert_i16_to_f32(block->data,block_f32->data,block_f32->length); + #define I16_TO_F32_NORM_FACTOR (3.051757812500000E-05) //which is 1/32768 + for (int i=0; ilength; i++) + block_f32->data[i] = (float32_t)block->data[i] * I16_TO_F32_NORM_FACTOR; AudioStream_F32::transmit(block_f32); AudioStream_F32::release(block_f32);