Correct for T4, add peak, rms, Gaussian

pull/11/head
boblark 4 years ago
parent 291f97c4ba
commit dbf79e1d1e
  1. 7
      AudioMixer_F32.cpp
  2. 8
      OpenAudio_ArduinoLibrary.h
  3. 90
      analyze_peak_f32.cpp
  4. 103
      analyze_peak_f32.h
  5. 68
      analyze_rms_f32.cpp
  6. 105
      analyze_rms_f32.h
  7. 0
      control_tlv320aic3206.cpp.xxx
  8. 0
      control_tlv320aic3206.h.xxx
  9. 103
      examples/SignalNoise_float/SignalNoise_float.ino
  10. 0
      input_i2s_f32.cpp.xxx
  11. 0
      input_i2s_f32.h.xxx
  12. 0
      output_i2s_f32.cpp.xxx
  13. 0
      output_i2s_f32.h.xxx
  14. 11
      readme.md
  15. 95
      synth_GaussianWhiteNoise_F32.cpp
  16. 76
      synth_GaussianWhiteNoise_F32.h
  17. 13
      synth_pinknoise_f32.cpp
  18. 6
      synth_pinknoise_f32.h
  19. 10
      synth_sine_f32.cpp
  20. 3
      synth_sine_f32.h
  21. 7
      synth_whitenoise_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" #include "AudioMixer_F32.h"
void AudioMixer4_F32::update(void) { 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); 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); in = receiveReadOnly_f32(channel);
if (!in) { if (!in) {
continue; 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 arm_scale_f32(out->data, multiplier[0], out->data, out->length); //scale the first input channel
//load and process the rest of the channels //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); in = receiveReadOnly_f32(channel);
if (!in) { if (!in) {
continue; continue;

@ -17,11 +17,15 @@
#include "AudioMixer_F32.h" #include "AudioMixer_F32.h"
#include "AudioMultiply_F32.h" #include "AudioMultiply_F32.h"
#include "AudioSettings_F32.h" #include "AudioSettings_F32.h"
#include "input_i2s_f32.h" // #include "input_i2s_f32.h" needs fixing, set to .xxx
#include "output_i2s_f32.h" // #include "output_i2s_f32.h" needs fixing, set to .xxx
#include "play_queue_f32.h" #include "play_queue_f32.h"
#include "record_queue_f32.h" #include "record_queue_f32.h"
#include "synth_pinknoise_f32.h" #include "synth_pinknoise_f32.h"
#include "synth_sine_f32.h" #include "synth_sine_f32.h"
#include "synth_waveform_F32.h" #include "synth_waveform_F32.h"
#include "synth_whitenoise_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

@ -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 (d<min) min=d;
if (d>max) 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);
}

@ -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

@ -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));
}

@ -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

@ -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);
}

@ -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: **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 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. 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__ . 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. **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.

@ -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; i<blockSize; i++) {
rdev = 0.0f;
for (int j=0; j<12; j++){ // Add 12, using Central Limit to get Gaussian
idum = (uint32_t)1664525 * idum + (uint32_t)1013904223;
it = FL_ONE | (FL_MASK & idum); // Generate random number
rdev += (*(float *)&it) - 1.0f; // Cute convert to float
/* ====================================
union (
uint32_t i32;
float32_t f32;
) uinf;
uinf.i32 = it;
rdev += uinf.f32 - 1.0f;
===================================
*/
}
// Next, to get general form
// return mu + sd * 3.4641016f * (rdev - 0.5*(float)M) / sqrtf((float32_t)M);
*pd++ = sd*(rdev - 6.0f); // Specific for mu=0.0, M=12
}
AudioStream_F32::transmit(blockOut);
AudioStream_F32::release(blockOut);
#if TEST_TIME_GWN
t2 = tElapse;
if(iitt++ < 0) {
Serial.print("At Gaussian Noise end, microseconds = ");
Serial.println (t2 - t1);
}
t1 = tElapse;
#endif
}

@ -0,0 +1,76 @@
/*
* synth_GaussianWhiteNoise_F32.h
* W7PUA 15 June 2020
*
* Thanks to PJRC and Pau Stoffregen for the Teensy processor, Teensyduino
* and Teensy Audio. Thanks to Chip Audette for the F32 extension
* work. Alll of that makes this possible. Bob
*
* Copyright (c) 2020 Bob Larkin
*
* 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.
*/
/* This noise source is very close to a Gaussian distribution with mean of
* zero and a standard deviation specified by amplitude(). Default amlitude
* is 0.0 (off). Time requirements:
* For generating a block of 128, Teensy 3.6, 121 microseconds
* For generating a block of 128, Teensy 4.0, 36 microseconds
*/
#ifndef synth_GaussianWhiteNoise_f32_h_
#define synth_GaussianWhiteNoise_f32_h_
#include "Arduino.h"
#include "AudioStream_F32.h"
// Temporary timing test
#define TEST_TIME_GWN 0
#define FL_ONE 0X3F800000
#define FL_MASK 0X007FFFFF
class AudioSynthGaussian_F32 : public AudioStream_F32
{
//GUI: inputs:0, outputs:1 //this line used for automatic generation of GUI node
//GUI: shortName:Gaussianwhitenoise //this line used for automatic generation of GUI node
public:
AudioSynthGaussian_F32() : AudioStream_F32(0, NULL) { }
// Allow for changing block size?
AudioSynthGaussian_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) { }
// Gaussian amplitude is specified by the 1-sigma (standard deviation) value.
// sd=0.0 is un-enabled.
void amplitude(float _sd) {
sd = _sd; // Enduring copy
if (sd<0.0) sd=0.0;
}
// Add printError(uint16_t e) - not currently used.
virtual void update(void);
private:
uint16_t blockSize = AUDIO_BLOCK_SAMPLES;
uint32_t idum = 12345;
float32_t sd = 0.0; // Default to off
uint16_t errorPrint = 0;
// *Temporary* - TEST_TIME allows measuring time in microseconds for each part of the update()
#if TEST_TIME_GWN
elapsedMicros tElapse;
int32_t iitt = 999000; // count up to a million during startup
#endif
};
#endif

@ -1,6 +1,7 @@
/* /*
Extended to f32 data Extended to f32 data
Created: Chip Audette, OpenAudio, Feb 2017 Created: Chip Audette, OpenAudio, Feb 2017
Included I16 to F32 conversion here. Bob Larkin June 2020
License: MIT License. Use at your own risk. License: MIT License. Use at your own risk.
*/ */
@ -43,7 +44,6 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#include "synth_pinknoise_f32.h" #include "synth_pinknoise_f32.h"
#include "input_i2s_f32.h" //for the audio_convert_i16_to_f32 routine
int16_t AudioSynthNoisePink_F32::instance_cnt = 0; int16_t AudioSynthNoisePink_F32::instance_cnt = 0;
@ -92,12 +92,14 @@ void AudioSynthNoisePink_F32::update(void)
int32_t taps; int32_t taps;
if (!enabled) return; if (!enabled) return;
gain = level; gain = level;
if (gain == 0) return; if (gain == 0) return;
block = AudioStream::allocate(); block = AudioStream::allocate();
block_f32 = AudioStream_F32::allocate_f32(); block_f32 = AudioStream_F32::allocate_f32();
if (!block | !block_f32) return; if (!block | !block_f32) return;
p = (uint32_t *)(block->data); p = (uint32_t *)(block->data);
//end = p + AUDIO_BLOCK_SAMPLES/2; //end = p + AUDIO_BLOCK_SAMPLES/2;
end = p + (block_f32->length)/2; end = p + (block_f32->length)/2;
@ -153,14 +155,15 @@ void AudioSynthNoisePink_F32::update(void)
pdec = dec; pdec = dec;
paccu = accu; paccu = accu;
plfsr = lfsr; plfsr = lfsr;
//convert int16 to f32 //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; i<block_f32->length; i++)
block_f32->data[i] = (float32_t)block->data[i] * I16_TO_F32_NORM_FACTOR;
AudioStream_F32::transmit(block_f32); AudioStream_F32::transmit(block_f32);
AudioStream_F32::release(block_f32); AudioStream_F32::release(block_f32);
AudioStream::release(block); AudioStream::release(block);
} }

@ -65,7 +65,9 @@ public:
level = (int32_t)(n * 65536.0); level = (int32_t)(n * 65536.0);
} }
virtual void update(void); virtual void update(void);
int enabled = 0;
int enabled = 1; //0;
private: private:
static const uint8_t pnmask[256]; static const uint8_t pnmask[256];
static const int32_t pfira[64]; static const int32_t pfira[64];
@ -76,7 +78,7 @@ private:
int32_t pdec; // decrement for all noise sources int32_t pdec; // decrement for all noise sources
int32_t paccu; // accumulator int32_t paccu; // accumulator
uint8_t pncnt; // overflowing counter as index to pnmask[] 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 #endif

@ -18,7 +18,6 @@ extern "C" {
extern const int16_t AudioWaveformSine[257]; extern const int16_t AudioWaveformSine[257];
} }
void AudioSynthWaveformSine_F32::update(void) void AudioSynthWaveformSine_F32::update(void)
{ {
audio_block_f32_t *block; audio_block_f32_t *block;
@ -40,19 +39,16 @@ void AudioSynthWaveformSine_F32::update(void)
scale = (ph >> 8) & 0xFFFF; scale = (ph >> 8) & 0xFFFF;
val2 *= scale; val2 *= scale;
val1 *= 0x10000 - scale; val1 *= 0x10000 - scale;
#if defined(KINETISK) #if (defined(KINETISK) || defined(__IMXRT1062__) )
block->data[i] = (float) multiply_32x32_rshift32(val1 + val2, magnitude); block->data[i] = (float) multiply_32x32_rshift32(val1 + val2, magnitude);
#elif defined(KINETISL) #elif defined(KINETISL)
block->data[i] = (float) ((((val1 + val2) >> 16) * magnitude) >> 16); block->data[i] = (float) ((((val1 + val2) >> 16) * magnitude) >> 16);
#endif #endif
ph += inc; ph += inc;
block->data[i] = block->data[i] / 32767.0f; // scale to float block->data[i] = block->data[i] / 32767.0f; // scale to float
} }
phase_accumulator = ph; phase_accumulator = ph;
AudioStream_F32::transmit(block); AudioStream_F32::transmit(block);
AudioStream_F32::release(block); AudioStream_F32::release(block);
return; return;

@ -60,7 +60,4 @@ private:
float sample_rate_Hz = AUDIO_SAMPLE_RATE; float sample_rate_Hz = AUDIO_SAMPLE_RATE;
volatile uint8_t enabled = 1; volatile uint8_t enabled = 1;
}; };
#endif #endif

@ -33,7 +33,6 @@
*/ */
#include "synth_whitenoise_f32.h" #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 // Park-Miller-Carta Pseudo-Random Number Generator
// http://www.firstpr.com.au/dsp/rand31/ // http://www.firstpr.com.au/dsp/rand31/
@ -111,9 +110,11 @@ void AudioSynthNoiseWhite_F32::update(void)
#endif #endif
} while (p < end); } while (p < end);
seed = lo; seed = lo;
//convert int16 to f32 //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; i<block_f32->length; i++)
block_f32->data[i] = (float32_t)block->data[i] * I16_TO_F32_NORM_FACTOR;
AudioStream_F32::transmit(block_f32); AudioStream_F32::transmit(block_f32);
AudioStream_F32::release(block_f32); AudioStream_F32::release(block_f32);

Loading…
Cancel
Save