Add i/o F32 from Chip Audette's Tympan library.

pull/11/head
boblark 4 years ago
parent 274108bd7b
commit 89afca0c8f
  1. 37
      AudioEffectCompWDRC_F32.h
  2. 2
      AudioMultiply_F32.h
  3. 28
      AudioSettings_F32.cpp
  4. 60
      AudioStream_F32.cpp
  5. 4
      OpenAudio_ArduinoLibrary.h
  6. 50
      examples/PassthroughF32/PassthroughF32.ino
  7. 44
      examples/SineCosOut/SineCosOut.ino
  8. 1316
      input_i2s_f32.cpp
  9. 167
      input_i2s_f32.h
  10. 1681
      output_i2s_f32.cpp
  11. 234
      output_i2s_f32.h
  12. 94
      play_queue_f32.cpp
  13. 61
      play_queue_f32.h
  14. 72
      synth_GaussianWhiteNoise_F32.cpp
  15. 81
      synth_sine_f32.cpp

@ -25,8 +25,8 @@ class AudioCalcGainWDRC_F32; //forward declared. Actually defined in later hea
class AudioEffectCompWDRC_F32 : public AudioStream_F32 class AudioEffectCompWDRC_F32 : public AudioStream_F32
{ {
//GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node //GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node
//GUI: shortName: CompressWDRC //GUI: shortName: CompressWDRC
public: public:
AudioEffectCompWDRC_F32(void): AudioStream_F32(1,inputQueueArray) { //need to modify this for user to set sample rate AudioEffectCompWDRC_F32(void): AudioStream_F32(1,inputQueueArray) { //need to modify this for user to set sample rate
setSampleRate_Hz(AUDIO_SAMPLE_RATE); setSampleRate_Hz(AUDIO_SAMPLE_RATE);
@ -47,7 +47,7 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
//allocate memory for the output of our algorithm //allocate memory for the output of our algorithm
audio_block_f32_t *out_block = AudioStream_F32::allocate_f32(); audio_block_f32_t *out_block = AudioStream_F32::allocate_f32();
if (!out_block) return; if (!out_block) return;
Serial.print("data37= "); Serial.print(block->data[37], 6);
//do the algorithm //do the algorithm
compress(block->data, out_block->data, block->length); compress(block->data, out_block->data, block->length);
@ -76,13 +76,14 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
audio_block_f32_t *envelope_block = AudioStream_F32::allocate_f32(); audio_block_f32_t *envelope_block = AudioStream_F32::allocate_f32();
if (!envelope_block) return; if (!envelope_block) return;
calcEnvelope.smooth_env(x, envelope_block->data, n); calcEnvelope.smooth_env(x, envelope_block->data, n);
Serial.print(" Envelope37= "); Serial.print(envelope_block->data[37], 6);
//float *xpk = envelope_block->data; //get pointer to the array of (empty) data values //float *xpk = envelope_block->data; //get pointer to the array of (empty) data values
//calculate gain //calculate gain
audio_block_f32_t *gain_block = AudioStream_F32::allocate_f32(); audio_block_f32_t *gain_block = AudioStream_F32::allocate_f32();
if (!gain_block) return; if (!gain_block) return;
calcGain.calcGainFromEnvelope(envelope_block->data, gain_block->data, n); calcGain.calcGainFromEnvelope(envelope_block->data, gain_block->data, n);
Serial.print(" Gain37= "); Serial.println(envelope_block->data[37], 6);
//apply gain //apply gain
arm_mult_f32(x, gain_block->data, y, n); arm_mult_f32(x, gain_block->data, y, n);
@ -95,7 +96,7 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
void setDefaultValues(void) { void setDefaultValues(void) {
//set default values...configure as limitter //set default values...configure as limitter
BTNRH_WDRC::CHA_WDRC gha = { BTNRH_WDRC::CHA_WDRC gha = {
5.0f, // attack time (ms) 5.0f, // attack time (ms)
50.0f, // release time (ms) 50.0f, // release time (ms)
24000.0f, // fs, sampling rate (Hz), THIS IS IGNORED! 24000.0f, // fs, sampling rate (Hz), THIS IS IGNORED!
115.0f, // maxdB, maximum signal (dB SPL)...assumed SPL for full-scale input signal 115.0f, // maxdB, maximum signal (dB SPL)...assumed SPL for full-scale input signal
@ -134,23 +135,23 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
calcEnvelope.setSampleRate_Hz(_fs_Hz); calcEnvelope.setSampleRate_Hz(_fs_Hz);
} }
void setAttackRelease_msec(const float atk_msec, const float rel_msec) { void setAttackRelease_msec(const float atk_msec, const float rel_msec) {
calcEnvelope.setAttackRelease_msec(atk_msec, rel_msec); calcEnvelope.setAttackRelease_msec(atk_msec, rel_msec);
} }
void setKneeLimiter_dBSPL(float _bolt) { calcGain.setKneeLimiter_dBSPL(_bolt); } void setKneeLimiter_dBSPL(float _bolt) { calcGain.setKneeLimiter_dBSPL(_bolt); }
void setKneeLimiter_dBFS(float _bolt_dBFS) { calcGain.setKneeLimiter_dBFS(_bolt_dBFS); } void setKneeLimiter_dBFS(float _bolt_dBFS) { calcGain.setKneeLimiter_dBFS(_bolt_dBFS); }
void setGain_dB(float _gain_dB) { calcGain.setGain_dB(_gain_dB); } //gain at start of compression void setGain_dB(float _gain_dB) { calcGain.setGain_dB(_gain_dB); } //gain at start of compression
void setKneeCompressor_dBSPL(float _tk) { calcGain.setKneeCompressor_dBSPL(_tk); } void setKneeCompressor_dBSPL(float _tk) { calcGain.setKneeCompressor_dBSPL(_tk); }
void setKneeCompressor_dBFS(float _tk_dBFS) { calcGain.setKneeCompressor_dBFS(_tk_dBFS); } void setKneeCompressor_dBFS(float _tk_dBFS) { calcGain.setKneeCompressor_dBFS(_tk_dBFS); }
void setCompRatio(float _cr) { calcGain.setCompRatio(_cr); } void setCompRatio(float _cr) { calcGain.setCompRatio(_cr); }
void setMaxdB(float _maxdB) { calcGain.setMaxdB(_maxdB); }; void setMaxdB(float _maxdB) { calcGain.setMaxdB(_maxdB); };
float getCurrentLevel_dB(void) { return AudioCalcGainWDRC_F32::db2(calcEnvelope.getCurrentLevel()); } //this is 20*log10(abs(signal)) after the envelope smoothing float getCurrentLevel_dB(void) { return AudioCalcGainWDRC_F32::db2(calcEnvelope.getCurrentLevel()); } //this is 20*log10(abs(signal)) after the envelope smoothing
float getGain_dB(void) { return calcGain.getGain_dB(); } //returns the linear gain of the system float getGain_dB(void) { return calcGain.getGain_dB(); } //returns the linear gain of the system
float getCurrentGain(void) { return calcGain.getCurrentGain(); } float getCurrentGain(void) { return calcGain.getCurrentGain(); }
float getCurrentGain_dB(void) { return calcGain.getCurrentGain_dB(); } float getCurrentGain_dB(void) { return calcGain.getCurrentGain_dB(); }
AudioCalcEnvelope_F32 calcEnvelope; AudioCalcEnvelope_F32 calcEnvelope;
AudioCalcGainWDRC_F32 calcGain; AudioCalcGainWDRC_F32 calcGain;

@ -20,7 +20,7 @@ class AudioMultiply_F32 : public AudioStream_F32
//GUI: inputs:2, outputs:1 //this line used for automatic generation of GUI node //GUI: inputs:2, outputs:1 //this line used for automatic generation of GUI node
public: public:
AudioMultiply_F32(void) : AudioStream_F32(2, inputQueueArray_f32) {}; AudioMultiply_F32(void) : AudioStream_F32(2, inputQueueArray_f32) {};
AudioMultiply_F32(const AudioSettings_F32 &settings) : AudioStream_F32(2, inputQueueArray_f32) {}; AudioMultiply_F32(const AudioSettings_F32 &settings) : AudioStream_F32(2, inputQueueArray_f32) {};
void update(void); void update(void);

@ -4,26 +4,26 @@
#include "AudioStream_F32.h" #include "AudioStream_F32.h"
float AudioSettings_F32::cpu_load_percent(const int n) { float AudioSettings_F32::cpu_load_percent(const int n) {
//n is the number of cycles //n is the number of cycles
#define CYCLE_COUNTER_APPROX_PERCENT(n) (((n) + (F_CPU / 32 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) / (F_CPU / 16 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) // #define CYCLE_COUNTER_APPROX_PERCENT(n) (((n) + (F_CPU / 32 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) / (F_CPU / 16 / AUDIO_SAMPLE_RATE * AUDIO_BLOCK_SAMPLES / 100)) removed per @jcj83429 21 Dec 20 defined double
float foo1 = ((float)(F_CPU / 32))/sample_rate_Hz; float foo1 = ((float)(F_CPU / 32))/sample_rate_Hz;
foo1 *= ((float)audio_block_samples); foo1 *= ((float)audio_block_samples);
foo1 /= 100.f; foo1 /= 100.f;
foo1 += (float)n; foo1 += (float)n;
float foo2 = (float)(F_CPU / 16)/sample_rate_Hz; float foo2 = (float)(F_CPU / 16)/sample_rate_Hz;
foo2 *= ((float)audio_block_samples); foo2 *= ((float)audio_block_samples);
foo2 /= 100.f; foo2 /= 100.f;
return foo1 / foo2; return foo1 / foo2;
//return (((n) + (F_CPU / 32 / sample_rate_Hz * audio_block_samples / 100)) / (F_CPU / 16 / sample_rate_Hz * audio_block_samples / 100)); //return (((n) + (F_CPU / 32 / sample_rate_Hz * audio_block_samples / 100)) / (F_CPU / 16 / sample_rate_Hz * audio_block_samples / 100));
} }
float AudioSettings_F32::processorUsage(void) { float AudioSettings_F32::processorUsage(void) {
return cpu_load_percent(AudioStream::cpu_cycles_total); return cpu_load_percent(AudioStream::cpu_cycles_total);
}; };
float AudioSettings_F32::processorUsageMax(void) { float AudioSettings_F32::processorUsageMax(void) {
return cpu_load_percent(AudioStream::cpu_cycles_total_max); return cpu_load_percent(AudioStream::cpu_cycles_total_max);
} }
void AudioSettings_F32::processorUsageMaxReset(void) { void AudioSettings_F32::processorUsageMaxReset(void) {
AudioStream::cpu_cycles_total_max = AudioStream::cpu_cycles_total; AudioStream::cpu_cycles_total_max = AudioStream::cpu_cycles_total;
} }

@ -8,21 +8,21 @@ uint8_t AudioStream_F32::f32_memory_used = 0;
uint8_t AudioStream_F32::f32_memory_used_max = 0; uint8_t AudioStream_F32::f32_memory_used_max = 0;
audio_block_f32_t* allocate_f32_memory(const int num) { audio_block_f32_t* allocate_f32_memory(const int num) {
static bool firstTime=true; static bool firstTime=true;
static audio_block_f32_t *data_f32; static audio_block_f32_t *data_f32;
if (firstTime == true) { if (firstTime == true) {
firstTime = false; firstTime = false;
data_f32 = new audio_block_f32_t[num]; data_f32 = new audio_block_f32_t[num];
} }
return data_f32; return data_f32;
} }
void AudioMemory_F32(const int num) { void AudioMemory_F32(const int num) {
audio_block_f32_t *data_f32 = allocate_f32_memory(num); audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num); if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num);
} }
void AudioMemory_F32(const int num, const AudioSettings_F32 &settings) { void AudioMemory_F32(const int num, const AudioSettings_F32 &settings) {
audio_block_f32_t *data_f32 = allocate_f32_memory(num); audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num, settings); if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num, settings);
} }
// Set up the pool of audio data blocks // Set up the pool of audio data blocks
@ -31,8 +31,8 @@ void AudioStream_F32::initialize_f32_memory(audio_block_f32_t *data, unsigned in
{ {
unsigned int i; unsigned int i;
//Serial.println("AudioStream_F32 initialize_memory"); // Serial.println("AudioStream_F32 initialize_memory");
//delay(10); // delay(10);
if (num > 192) num = 192; if (num > 192) num = 192;
__disable_irq(); __disable_irq();
f32_memory_pool = data; f32_memory_pool = data;
@ -42,6 +42,7 @@ void AudioStream_F32::initialize_f32_memory(audio_block_f32_t *data, unsigned in
for (i=0; i < num; i++) { for (i=0; i < num; i++) {
f32_memory_pool_available_mask[i >> 5] |= (1 << (i & 0x1F)); f32_memory_pool_available_mask[i >> 5] |= (1 << (i & 0x1F));
} }
for (i=0; i < num; i++) { for (i=0; i < num; i++) {
data[i].memory_pool_index = i; data[i].memory_pool_index = i;
} }
@ -52,8 +53,8 @@ void AudioStream_F32::initialize_f32_memory(audio_block_f32_t *data, unsigned in
{ {
initialize_f32_memory(data,num); initialize_f32_memory(data,num);
for (unsigned int i=0; i < num; i++) { for (unsigned int i=0; i < num; i++) {
data[i].fs_Hz = settings.sample_rate_Hz; data[i].fs_Hz = settings.sample_rate_Hz;
data[i].length = settings.audio_block_samples; data[i].length = settings.audio_block_samples;
} }
} // end initialize_memory } // end initialize_memory
@ -66,7 +67,19 @@ audio_block_f32_t * AudioStream_F32::allocate_f32(void)
audio_block_f32_t *block; audio_block_f32_t *block;
uint8_t used; uint8_t used;
// f32_memory_pool_available_mask is array of six 32-bit uints with a 1 in position of
// each available block (max 192). 0 if unavailable (busy) or not allocated at all.
p = f32_memory_pool_available_mask; p = f32_memory_pool_available_mask;
/*
if(millis() > 1200) {
Serial.print("AudioStream_F32 ");
Serial.println((uint32_t)*p, BIN); // Just first of 6
}
*/
__disable_irq(); __disable_irq();
do { do {
avail = *p; if (avail) break; avail = *p; if (avail) break;
@ -76,7 +89,7 @@ audio_block_f32_t * AudioStream_F32::allocate_f32(void)
p++; avail = *p; if (avail) break; p++; avail = *p; if (avail) break;
p++; avail = *p; if (avail) break; p++; avail = *p; if (avail) break;
__enable_irq(); __enable_irq();
//Serial.println("alloc_f32:null"); // Serial.println("alloc_f32:null");
return NULL; return NULL;
} while (0); } while (0);
n = __builtin_clz(avail); n = __builtin_clz(avail);
@ -88,8 +101,7 @@ audio_block_f32_t * AudioStream_F32::allocate_f32(void)
block = f32_memory_pool + ((index << 5) + (31 - n)); block = f32_memory_pool + ((index << 5) + (31 - n));
block->ref_count = 1; block->ref_count = 1;
if (used > f32_memory_used_max) f32_memory_used_max = used; if (used > f32_memory_used_max) f32_memory_used_max = used;
//Serial.print("alloc_f32:"); // Serial.print("alloc_f32:"); Serial.println((uint32_t)block, HEX);
//Serial.println((uint32_t)block, HEX);
return block; return block;
} }
@ -106,8 +118,7 @@ void AudioStream_F32::release(audio_block_f32_t *block)
if (block->ref_count > 1) { if (block->ref_count > 1) {
block->ref_count--; block->ref_count--;
} else { } else {
//Serial.print("release_f32:"); //Serial.print("release_f32:"); Serial.println((uint32_t)block, HEX);
//Serial.println((uint32_t)block, HEX);
f32_memory_pool_available_mask[index] |= mask; f32_memory_pool_available_mask[index] |= mask;
f32_memory_used--; f32_memory_used--;
} }
@ -125,11 +136,11 @@ void AudioStream_F32::transmit(audio_block_f32_t *block, unsigned char index)
{ {
//Serial.print("AudioStream_F32: transmit(). start...index = ");Serial.println(index); //Serial.print("AudioStream_F32: transmit(). start...index = ");Serial.println(index);
for (AudioConnection_F32 *c = destination_list_f32; c != NULL; c = c->next_dest) { for (AudioConnection_F32 *c = destination_list_f32; c != NULL; c = c->next_dest) {
//Serial.print(" : loop1, c->src_index = ");Serial.println(c->src_index); //Serial.print(" : loop1, c->src_index = ");Serial.println(c->src_index);
if (c->src_index == index) { if (c->src_index == index) {
//Serial.println(" : if1"); //Serial.println(" : if1");
if (c->dst.inputQueue_f32[c->dest_index] == NULL) { if (c->dst.inputQueue_f32[c->dest_index] == NULL) {
//Serial.println(" : if2"); //Serial.println(" : if2");
c->dst.inputQueue_f32[c->dest_index] = block; c->dst.inputQueue_f32[c->dest_index] = block;
block->ref_count++; block->ref_count++;
//Serial.print(" : block->ref_count = "); Serial.println(block->ref_count); //Serial.print(" : block->ref_count = "); Serial.println(block->ref_count);
@ -144,14 +155,13 @@ void AudioStream_F32::transmit(audio_block_f32_t *block, unsigned char index)
audio_block_f32_t * AudioStream_F32::receiveReadOnly_f32(unsigned int index) audio_block_f32_t * AudioStream_F32::receiveReadOnly_f32(unsigned int index)
{ {
audio_block_f32_t *in; audio_block_f32_t *in;
//Serial.print(index); Serial.print(" <index RcvReadOnly() num_inputs_f32> "); Serial.println(num_inputs_f32);
if (index >= num_inputs_f32) return NULL; if (index >= num_inputs_f32) return NULL;
in = inputQueue_f32[index]; in = inputQueue_f32[index];
inputQueue_f32[index] = NULL; inputQueue_f32[index] = NULL;
return in; return in;
} }
// Receive block from an input. The block will not // Receive block from an input. The block will not
// be shared, so its contents may be changed. // be shared, so its contents may be changed.
audio_block_f32_t * AudioStream_F32::receiveWritable_f32(unsigned int index) audio_block_f32_t * AudioStream_F32::receiveWritable_f32(unsigned int index)

@ -17,8 +17,8 @@
#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_OA_f32.h"
#include "output_i2s_OA_f32.h" #include "output_i2s_OA_F32.h"
#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"

@ -0,0 +1,50 @@
/*
PassthroughF32.ino - Stereo passthrough.
Bob Larkin 22 Dec 2020
Basic test of I2S input and output.
Tested T3.6 and 5 Jan 2021
Public Domain
*/
#include "Arduino.h"
#include "Audio.h" // Teensy I16 Audio Library
#include "OpenAudio_ArduinoLibrary.h" // F32 library
#include "AudioStream_F32.h"
/*
#include "Audio.h" // Teensy I16 Audio Library
#include "OpenAudio_ArduinoLibrary.h" // F32 library
#include "AudioStream_F32.h" */
// AudioInputI2S_OA_F32 i2sIn;
AudioInputI2S_F32 i2sIn;
AudioAnalyzePeak_F32 peakL;
AudioAnalyzePeak_F32 peakR;
// AudioOutputI2S_OA_F32 i2sOut;
AudioOutputI2S_F32 i2sOut;
AudioConnection_F32 patchCord0(i2sIn, 0, peakL, 0);
AudioConnection_F32 patchCord1(i2sIn, 1, peakR, 0);
AudioConnection_F32 patchCord2(i2sIn, 0, i2sOut, 0);
AudioConnection_F32 patchCord3(i2sIn, 1, i2sOut, 1);
AudioControlSGTL5000 codec1;
void setup() {
Serial.begin(9600); // (anything)
delay(1000);
Serial.println("OpenAudio_ArduinoLibrary - Passthrough Stereo");
// Internally, I16 blocks are used Bob Fix sometime
// AudioMemory(4); // Needed or I/O
AudioMemory_F32(20);
codec1.enable(); // MUST be before inputSelect()
codec1.inputSelect(AUDIO_INPUT_LINEIN);
}
void loop() {
Serial.print("Max float memory = ");
Serial.println(AudioStream_F32::f32_memory_used_max);
if(peakL.available()) Serial.print(peakL.read(), 6);
Serial.print(" <-L R-> ");
if(peakR.available()) Serial.println(peakR.read(), 6);
delay(1000);
}

@ -0,0 +1,44 @@
/*
SineCosOut.ino - Sine left, Cos right
Bob Larkin 28 Dec 2020
Basic test of I2S input and output.
Tested on T3.6 and T4.0
Public Domain
*/
#include "Audio.h" // Teensy I16 Audio Library
#include "OpenAudio_ArduinoLibrary.h" // F32 library
#include "AudioStream_F32.h"
AudioSynthSineCosine_F32 sineCos;
AudioAnalyzePeak_F32 peakL;
AudioAnalyzePeak_F32 peakR;
//AudioOutputI2S_OA_F32 i2sOut;
AudioOutputI2S_F32 i2sOut;
AudioConnection_F32 patchCord0(sineCos, 0, peakL, 0);
AudioConnection_F32 patchCord1(sineCos, 1, peakR, 0);
AudioConnection_F32 patchCord2(sineCos, 0, i2sOut, 0); // Sine
AudioConnection_F32 patchCord3(sineCos, 1, i2sOut, 1); // Cosine
AudioControlSGTL5000 codec1;
void setup() {
Serial.begin(9600); // (anything)
delay(1000);
Serial.println("OpenAudio_ArduinoLibrary - Sine-Cosine Stereo");
// Internally, I16 memory blocks are used. Needs modification, but
// for now, supply 4 for F32 input and 4 for F32 output (shared).
AudioMemory(4);
AudioMemory_F32(20);
codec1.enable(); // MUST be before inputSelect()
codec1.inputSelect(AUDIO_INPUT_LINEIN);
sineCos.amplitude(0.2); sineCos.frequency(600.0f);
}
void loop() {
Serial.print("Max float memory = ");
Serial.println(AudioStream_F32::f32_memory_used_max);
if(peakL.available()) Serial.print(peakL.read(), 6);
Serial.print(" <-L R-> ");
if(peakR.available()) Serial.println(peakR.read(), 6);
delay(500);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,167 @@
/*
* ***** input_i2s_f32.h ******
*
* 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.
*/
/*
* Extended by Chip Audette, OpenAudio, May 2019
* Converted to F32 and to variable audio block length
* The F32 conversion is under the MIT License. Use at your own risk.
*/
#ifndef _input_i2s_f32_h_
#define _input_i2s_f32_h_
#include <Arduino.h>
#include <arm_math.h>
#include "AudioStream_F32.h"
#include "AudioStream.h" //Do we really need this?? (Chip, 2020-10-31)
#include "DMAChannel.h"
class AudioInputI2S_F32 : public AudioStream_F32
{
//GUI: inputs:0, outputs:2 //this line used for automatic generation of GUI nodes
public:
AudioInputI2S_F32(void) : AudioStream_F32(0, NULL) { begin(); } //uses default AUDIO_SAMPLE_RATE and BLOCK_SIZE_SAMPLES from AudioStream.h
AudioInputI2S_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) {
sample_rate_Hz = settings.sample_rate_Hz;
audio_block_samples = settings.audio_block_samples;
begin();
}
virtual void update(void);
static void scale_i16_to_f32( float32_t *p_i16, float32_t *p_f32, int len) ;
static void scale_i24_to_f32( float32_t *p_i24, float32_t *p_f32, int len) ;
static void scale_i32_to_f32( float32_t *p_i32, float32_t *p_f32, int len);
void begin(void);
void begin(bool);
void sub_begin_i32(void);
//void sub_begin_i16(void);
int get_isOutOfMemory(void) { return flag_out_of_memory; }
void clear_isOutOfMemory(void) { flag_out_of_memory = 0; }
//friend class AudioOutputI2S_F32;
protected:
AudioInputI2S_F32(int dummy): AudioStream_F32(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility;
static DMAChannel dma;
static void isr_32(void);
static void isr(void);
virtual void update_1chan(int, audio_block_f32_t *&);
private:
static audio_block_f32_t *block_left_f32;
static audio_block_f32_t *block_right_f32;
static float sample_rate_Hz;
static int audio_block_samples;
static uint16_t block_offset;
static int flag_out_of_memory;
static unsigned long update_counter;
};
class AudioInputI2Sslave_F32 : public AudioInputI2S_F32
{
public:
AudioInputI2Sslave_F32(void) : AudioInputI2S_F32(0) { begin(); }
void begin(void);
friend void dma_ch1_isr(void);
};
#endif
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
#if 0
/* 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.
*/
#ifndef _input_i2s_OA_f32_h_
#define _input_i2s_OA_f32_h_
#include "Arduino.h"
#include "AudioStream_F32.h"
#include "AudioStream.h"
#include "DMAChannel.h"
#include "AudioSettings_F32.h"
class AudioInputI2S_OA_F32 : public AudioStream_F32
{
//GUI: inputs:0, outputs:2 //this line used for automatic generation of GUI nodes
public:
AudioInputI2S_OA_F32(void) : AudioStream_F32(0, NULL) { begin(); } //uses default AUDIO_SAMPLE_RATE and BLOCK_SIZE_SAMPLES from AudioStream.h
// For now, only allow 128 blocks and 44.1kHz
/* AudioInputI2S_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL) {
sample_rate_Hz = settings.sample_rate_Hz;
audio_block_samples = settings.audio_block_samples;
begin();
}
*/
virtual void update(void);
static void convert_i16_to_f32( int16_t *p_i16, float32_t *p_f32, int len) ;
void begin(void);
friend class AudioOutputI2S_OA_F32;
protected:
AudioInputI2S_OA_F32(int dummy): AudioStream_F32(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
static bool update_responsibility;
static DMAChannel dma;
static void isr(void);
private:
static audio_block_t *block_left;
static audio_block_t *block_right;
static float sample_rate_Hz_i;
static int audio_block_samples_i;
static uint16_t block_offset;
};
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,234 @@
/*
* ***** output_i2s_f32.h *****
*
* 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.
*/
/*
* Extended by Chip Audette, OpenAudio, May 2019
* Converted to F32 and to variable audio block length
* The F32 conversion is under the MIT License. Use at your own risk.
*/
#ifndef output_i2s_f32_h_
#define output_i2s_f32_h_
#include <Arduino.h>
#include <arm_math.h>
#include "AudioStream_F32.h"
//include "AudioStream.h"
#include "DMAChannel.h"
class AudioOutputI2S_F32 : public AudioStream_F32
{
//GUI: inputs:2, outputs:0 //this line used for automatic generation of GUI node
public:
AudioOutputI2S_F32(void) : AudioStream_F32(2, inputQueueArray) { begin();} //uses default AUDIO_SAMPLE_RATE and BLOCK_SIZE_SAMPLES from AudioStream.h
AudioOutputI2S_F32(const AudioSettings_F32 &settings) : AudioStream_F32(2, inputQueueArray)
{
sample_rate_Hz = settings.sample_rate_Hz;
audio_block_samples = settings.audio_block_samples;
begin();
}
virtual void update(void);
void begin(void);
void begin(bool);
void sub_begin_i32(void);
void sub_begin_i16(void);
friend class AudioInputI2S_F32;
friend class AudioInputI2S_F32;
#if defined(__IMXRT1062__)
friend class AudioOutputI2SQuad_F32;
friend class AudioInputI2SQuad_F32;
//friend class AudioOutputI2SHex;
//friend class AudioInputI2SHex;
//friend class AudioOutputI2SOct;
//friend class AudioInputI2SOct;
#endif
static void scale_f32_to_i16( float32_t *p_f32, float32_t *p_i16, int len) ;
static void scale_f32_to_i24( float32_t *p_f32, float32_t *p_i16, int len) ;
static void scale_f32_to_i32( float32_t *p_f32, float32_t *p_i32, int len) ;
static float setI2SFreq_T3(const float);
protected:
AudioOutputI2S_F32(int dummy): AudioStream_F32(2, inputQueueArray) {} // to be used only inside AudioOutputI2Sslave !!
static void config_i2s(void);
static void config_i2s(bool);
static void config_i2s(float);
static void config_i2s(bool, float);
//static void config_i2s_i16(void,float);
//static void config_i2s_i32(void,float);
static audio_block_f32_t *block_left_1st;
static audio_block_f32_t *block_right_1st;
static bool update_responsibility;
static DMAChannel dma;
static void isr_16(void);
static void isr_32(void);
static void isr(void);
private:
static audio_block_f32_t *block_left_2nd;
static audio_block_f32_t *block_right_2nd;
static uint16_t block_left_offset;
static uint16_t block_right_offset;
audio_block_f32_t *inputQueueArray[2];
static float sample_rate_Hz;
static int audio_block_samples;
volatile uint8_t enabled = 1;
};
class AudioOutputI2Sslave_F32 : public AudioOutputI2S_F32
{
public:
AudioOutputI2Sslave_F32(void) : AudioOutputI2S_F32(0) { begin(); } ;
void begin(void);
friend class AudioInputI2Sslave_F32;
friend void dma_ch0_isr(void);
protected:
static void config_i2s(void);
};
#endif
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
#if 0
/*
* output_i2s_OA_F32.h Revised for floating point input, but totally based
* on and forked from the Teensy Audio Library object output_i2s.cpp. Thus:
*
* 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.
*/
// 28 Dec 2020 Tested, master clock, at 44100, on T3.6 and T4.0 without problems Bob L.
#ifndef output_i2s_oa_f32_h_
#define output_i2s_oa_f32_h_
#include "Arduino.h"
#include "Audio.h"
#include "OpenAudio_ArduinoLibrary.h"
#include "AudioStream.h"
#include "AudioStream_F32.h"
#include "DMAChannel.h"
// #include "pins_teensy.c"
// Info: AUDIO_BLOCK_SAMPLES is 128, from AudioStream.h
// AUDIO_SAMPLE_RATE is 44117.64706 from AudioStream.h
class AudioOutputI2S_OA_F32 : public AudioStream_F32
{
//GUI: inputs:2, outputs:0 //this line used for automatic generation of GUI node
public:
AudioOutputI2S_OA_F32(void) : AudioStream_F32(2, inputQueueArray_f32) {
//sample_rate_Hz = AUDIO_SAMPLE_RATE;
//audio_block_samples = AUDIO_BLOCK_SAMPLES;
begin();
}
// AudioOutputI2S_OA_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32) {begin(); };
virtual void update(void);
void begin(void);
//friend class AudioInputI2S_OA_F32;
#if defined(__IMXRT1062__)
/*
friend class AudioOutputI2S_OA_F32Quad;
friend class AudioInputI2SQuad;
friend class AudioOutputI2S_OA_F32Hex;
friend class AudioInputI2SHex;
friend class AudioOutputI2S_OA_F32Oct;
friend class AudioInputI2SOct;
*/
#endif
static void config_i2s(void);
// volatile uint8_t enabled = 1;
protected:
AudioOutputI2S_OA_F32(int dummy): AudioStream_F32(2, inputQueueArray_f32) {} // to be used only inside AudioOutputI2S_OA_F32slave !!
static audio_block_t *block_left_1st;
static audio_block_t *block_right_1st;
static bool update_responsibility;
static DMAChannel dma;
static void isr(void);
private:
static uint32_t usec, usecLast;
static float sample_rate_Hz;
static int audio_block_samples;
static audio_block_t *block_left_2nd;
static audio_block_t *block_right_2nd;
static uint16_t block_left_offset;
static uint16_t block_right_offset;
audio_block_f32_t *inputQueueArray_f32[2];
};
class AudioOutputI2Sslave_OA_F32 : public AudioOutputI2S_OA_F32
{
public:
AudioOutputI2Sslave_OA_F32(void) : AudioOutputI2S_OA_F32(0) { begin(); } ;
void begin(void);
// friend class AudioInputI2Sslave;
friend void dma_ch0_isr(void);
protected:
static void config_i2s(void);
};
#endif
#endif

@ -1,10 +1,10 @@
/* /*
* AudioRecordQueue_F32 * AudioRecordQueue_F32
* *
* Created: Chip Audette (OpenAudio), Feb 2017 * Created: Chip Audette (OpenAudio), Feb 2017
* Extended from on Teensy Audio Library * Extended from on Teensy Audio Library
* *
* License: MIT License. Use at your own risk. * License: MIT License. Use at your own risk.
*/ */
#include "play_queue_f32.h" #include "play_queue_f32.h"
@ -12,63 +12,75 @@
bool AudioPlayQueue_F32::available(void) bool AudioPlayQueue_F32::available(void)
{ {
if (userblock) return true; if (userblock) return true;
userblock = allocate_f32(); userblock = allocate_f32();
if (userblock) return true; if (userblock) return true;
return false; return false;
} }
/* getBuffer() returns a pointer to the data area of an AudioBlock_32
* that can be loaded in the .INO. There is only one of these at a
* time, and they hold 128 float32_t. allocate_f32 will hold up
* a return from getBuffer() if Audio memory is not available. This will
* be freed up by update().
*/
float32_t * AudioPlayQueue_F32::getBuffer(void) float32_t * AudioPlayQueue_F32::getBuffer(void)
{ {
if (userblock) return userblock->data; if (userblock) return userblock->data;
while (1) { while (1) {
userblock = allocate_f32(); userblock = allocate_f32();
if (userblock) return userblock->data; if (userblock) return userblock->data;
yield(); yield();
} }
} }
/* playBuffer() can be called anytime after data is
* loaded to the data block pointed to by getBuffer).
* This function then enters the pointer to the queue,
* waiting to be sent in turn. If the queue is full,
* this function waits until a spot in the queue is opened
* up by update() (called by interrupts).
*/
void AudioPlayQueue_F32::playBuffer(void) void AudioPlayQueue_F32::playBuffer(void)
{ {
uint32_t h; uint32_t h;
if (!userblock) return; if (!userblock) return;
h = head + 1; h = head + 1;
if (h >= 32) h = 0; if (h >= 32) h = 0;
while (tail == h) ; // wait until space in the queue while (tail == h) ; // wait until space in the queue
queue[h] = userblock; queue[h] = userblock;
head = h; head = h;
userblock = NULL; userblock = NULL;
} }
void AudioPlayQueue_F32::update(void) void AudioPlayQueue_F32::update(void)
{ {
audio_block_f32_t *block; audio_block_f32_t *block;
uint32_t t; uint32_t t;
t = tail; t = tail;
if (t != head) { if (t != head) { // a data block is available to transmit out
if (++t >= 32) t = 0; if (++t >= 32) t = 0; // tail is advanced by one, circularly
block = queue[t]; block = queue[t]; // pointer to next block
tail = t; tail = t;
transmit(block); transmit(block);
release(block); release(block);
} }
} }
//assume user already has an audio_block that was NOT allocated by this //assume user already has an audio_block that was NOT allocated by this
//playBuffer. Here, you hand it your buffer. This object takes ownership //playBuffer. Here, you hand it your buffer. This object takes ownership
//of it and puts it into the queue //of it and puts it into the queue
void AudioPlayQueue_F32::playAudioBlock(audio_block_f32_t *audio_block) { void AudioPlayQueue_F32::playAudioBlock(audio_block_f32_t *audio_block) {
uint32_t h; uint32_t h;
if (!audio_block) return;
h = head + 1;
if (h >= 32) h = 0;
while (tail == h) ; // wait until space in the queue
queue[h] = audio_block;
audio_block->ref_count++; //take ownership of this block
head = h;
//userblock = NULL;
if (!audio_block) return;
h = head + 1;
if (h >= 32) h = 0;
while (tail == h) ; // wait until space in the queue
queue[h] = audio_block;
audio_block->ref_count++; //take ownership of this block
head = h;
//userblock = NULL;
} }

@ -1,11 +1,30 @@
/* /*
* AudioPlayQueue_F32 * AudioPlayQueue_F32
* *
* Created: Chip Audette (OpenAudio), Feb 2017 * Created: Chip Audette (OpenAudio), Feb 2017
* Extended from on Teensy Audio Library * Extended from on Teensy Audio Library
* *
* License: MIT License. Use at your own risk. * License: MIT License. Use at your own risk.
*
*/ */
/* Notes from Paul Stoffregen (from 4320 LED Video+Sound Project)
*
* AudioPlayQueue - Play audio data provided by the Arduino sketch.
* This object provides functions to allow the sketch code to push data
* into the audio system.
*
* getBuffer();
* Returns a pointer to an array of 128 int16.
* This buffer is within the audio library memory pool, providing the most
* efficient way to input data to the audio system. The buffer is likely
* to be populated by previously used data, so the entire 128 words should
* be written before calling playBuffer(). Only a single buffer should be
* requested at a time. This function may return NULL if no memory
* is available.
*
* playBuffer();
* Transmit the buffer previously obtained from getBuffer().
*/
#ifndef play_queue_f32_h_ #ifndef play_queue_f32_h_
#define play_queue_f32_h_ #define play_queue_f32_h_
@ -17,25 +36,25 @@ class AudioPlayQueue_F32 : public AudioStream_F32
{ {
//GUI: inputs:0, outputs:1 //this line used for automatic generation of GUI node //GUI: inputs:0, outputs:1 //this line used for automatic generation of GUI node
public: public:
AudioPlayQueue_F32(void) : AudioStream_F32(0, NULL), AudioPlayQueue_F32(void) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { } userblock(NULL), head(0), tail(0) { }
AudioPlayQueue_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL), AudioPlayQueue_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { } userblock(NULL), head(0), tail(0) { }
//void play(int16_t data); //void play(int16_t data);
//void play(const int16_t *data, uint32_t len); //void play(const int16_t *data, uint32_t len);
//void play(float32_t data); //void play(float32_t data);
//void play(const float32_t *data, uint32_t len); //void play(const float32_t *data, uint32_t len);
void playAudioBlock(audio_block_f32_t *); void playAudioBlock(audio_block_f32_t *); // Not in I16 library
bool available(void); bool available(void);
float32_t * getBuffer(void); float32_t * getBuffer(void);
void playBuffer(void); void playBuffer(void);
void stop(void); void stop(void);
//bool isPlaying(void) { return playing; } //bool isPlaying(void) { return playing; }
virtual void update(void); virtual void update(void);
private: private:
audio_block_f32_t *queue[32]; audio_block_f32_t *queue[32];
audio_block_f32_t *userblock; audio_block_f32_t *userblock;
volatile uint8_t head, tail; volatile uint8_t head, tail;
}; };
#endif #endif

@ -2,7 +2,7 @@
* synth_GaussianWhiteNoise_F32.cpp * synth_GaussianWhiteNoise_F32.cpp
* by Bob Larkin W7PUA 15 June 2020 * by Bob Larkin W7PUA 15 June 2020
* *
* Created: Chip Audette, OpenAudio, Feb 2017 * Created: Chip Audette, OpenAudio, Feb 2017
* *
@ -32,25 +32,25 @@
void AudioSynthGaussian_F32::update(void) void AudioSynthGaussian_F32::update(void)
{ {
audio_block_f32_t *blockOut; audio_block_f32_t *blockOut;
uint32_t it; uint32_t it;
float32_t rdev = 0.0f; float32_t rdev = 0.0f;
float32_t* pd; float32_t* pd;
if (sd < 0.01f) { if (sd < 0.01f) {
return; // Not enabled return; // Not enabled
} }
#if TEST_TIME_GWN #if TEST_TIME_GWN
if (iitt++ >1000000) iitt = -10; if (iitt++ >1000000) iitt = -10;
uint32_t t1, t2; uint32_t t1, t2;
t1 = tElapse; t1 = tElapse;
#endif #endif
blockOut = AudioStream_F32::allocate_f32(); blockOut = AudioStream_F32::allocate_f32();
if (!blockOut) { if (!blockOut) {
if(errorPrint) Serial.println("GWN-ERR: No output memory"); if(errorPrint) Serial.println("GWN-ERR: No output memory");
return; return;
} }
pd = &blockOut->data[0]; // Pointer to write data pd = &blockOut->data[0]; // Pointer to write data
/* The "Even Quicker" uniform random sample generator from D. E. Knuth and /* The "Even Quicker" uniform random sample generator from D. E. Knuth and
@ -58,44 +58,34 @@ void AudioSynthGaussian_F32::update(void)
* 2nd ed, with the comment "this is about as good as any 32-bit linear * 2nd ed, with the comment "this is about as good as any 32-bit linear
* congruential generator, entirely adequate for many uses." * congruential generator, entirely adequate for many uses."
*/ */
union {
// Try:
union {
uint32_t i32; uint32_t i32;
float32_t f32; float32_t f32;
} uinf; } uinf;
for(int i=0; i<blockSize; i++) {
for(int i=0; i<blockSize; i++) { rdev = 0.0f;
rdev = 0.0f; for (int j=0; j<12; j++){ // Add 12, using Central Limit to get Gaussian
for (int j=0; j<12; j++){ // Add 12, using Central Limit to get Gaussian idum = (uint32_t)1664525 * idum + (uint32_t)1013904223;
idum = (uint32_t)1664525 * idum + (uint32_t)1013904223; it = FL_ONE | (FL_MASK & idum); // Generate random number
it = FL_ONE | (FL_MASK & idum); // Generate random number /* dev += (*(float *)&it) - 1.0f; // Cute convert to float, but gets compiler warning */
uinf.i32 = it;
rdev += uinf.f32 - 1.0f;
// rdev += (*(float *)&it) - 1.0f; // Cute convert to float - Gets warning }
// Try // Next, to get general form
uinf.i32 = it; // return mu + sd * 3.4641016f * (rdev - 0.5*(float)M) / sqrtf((float32_t)M);
rdev += uinf.f32 - 1.0f; *pd++ = sd*(rdev - 6.0f); // Specific for mu=0.0, M=12
}
AudioStream_F32::transmit(blockOut);
AudioStream_F32::release(blockOut);
}
// 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 #if TEST_TIME_GWN
t2 = tElapse; t2 = tElapse;
if(iitt++ < 0) { if(iitt++ < 0) {
Serial.print("At Gaussian Noise end, microseconds = "); Serial.print("At Gaussian Noise end, microseconds = ");
Serial.println (t2 - t1); Serial.println (t2 - t1);
} }
t1 = tElapse; t1 = tElapse;
#endif #endif
} }

@ -18,48 +18,41 @@ 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; uint32_t i, ph, inc, index, scale;
uint32_t i, ph, inc, index, scale; int32_t val1, val2;
int32_t val1, val2; static uint32_t block_length = 0;
static uint32_t block_length = 0;
if (enabled) {
if (enabled) { if (magnitude) {
if (magnitude) { block = allocate_f32();
block = allocate_f32(); if (block) {
if (block) { block_length = (uint32_t)block->length;
block_length = (uint32_t)block->length; ph = phase_accumulator;
ph = phase_accumulator; inc = phase_increment;
inc = phase_increment; for (i=0; i < block_length; i++) {
for (i=0; i < block_length; i++) { index = ph >> 24;
index = ph >> 24; val1 = AudioWaveformSine[index];
val1 = AudioWaveformSine[index]; val2 = AudioWaveformSine[index+1];
val2 = AudioWaveformSine[index+1]; scale = (ph >> 8) & 0xFFFF;
scale = (ph >> 8) & 0xFFFF; val2 *= scale;
val2 *= scale; val1 *= 0x10000 - scale;
val1 *= 0x10000 - scale; #if (defined(KINETISK) || defined(__IMXRT1062__) )
#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; }
} }// end if (magnitude)
} phase_accumulator += phase_increment * block_length; // continue sine wave while magnitude==0
phase_accumulator += phase_increment * block_length; } // end if (enabled)
}
} }

Loading…
Cancel
Save