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

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

@ -25,8 +25,8 @@ class AudioCalcGainWDRC_F32; //forward declared. Actually defined in later hea
class AudioEffectCompWDRC_F32 : public AudioStream_F32
{
//GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node
//GUI: shortName: CompressWDRC
//GUI: inputs:1, outputs:1 //this line used for automatic generation of GUI node
//GUI: shortName: CompressWDRC
public:
AudioEffectCompWDRC_F32(void): AudioStream_F32(1,inputQueueArray) { //need to modify this for user to set 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
audio_block_f32_t *out_block = AudioStream_F32::allocate_f32();
if (!out_block) return;
Serial.print("data37= "); Serial.print(block->data[37], 6);
//do the algorithm
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();
if (!envelope_block) return;
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
//calculate gain
audio_block_f32_t *gain_block = AudioStream_F32::allocate_f32();
if (!gain_block) return;
calcGain.calcGainFromEnvelope(envelope_block->data, gain_block->data, n);
Serial.print(" Gain37= "); Serial.println(envelope_block->data[37], 6);
//apply gain
arm_mult_f32(x, gain_block->data, y, n);

@ -5,7 +5,7 @@
float AudioSettings_F32::cpu_load_percent(const int n) {
//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;
foo1 *= ((float)audio_block_samples);
foo1 /= 100.f;

@ -31,8 +31,8 @@ void AudioStream_F32::initialize_f32_memory(audio_block_f32_t *data, unsigned in
{
unsigned int i;
//Serial.println("AudioStream_F32 initialize_memory");
//delay(10);
// Serial.println("AudioStream_F32 initialize_memory");
// delay(10);
if (num > 192) num = 192;
__disable_irq();
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++) {
f32_memory_pool_available_mask[i >> 5] |= (1 << (i & 0x1F));
}
for (i=0; i < num; i++) {
data[i].memory_pool_index = i;
}
@ -66,7 +67,19 @@ audio_block_f32_t * AudioStream_F32::allocate_f32(void)
audio_block_f32_t *block;
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;
/*
if(millis() > 1200) {
Serial.print("AudioStream_F32 ");
Serial.println((uint32_t)*p, BIN); // Just first of 6
}
*/
__disable_irq();
do {
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;
__enable_irq();
//Serial.println("alloc_f32:null");
// Serial.println("alloc_f32:null");
return NULL;
} while (0);
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->ref_count = 1;
if (used > f32_memory_used_max) f32_memory_used_max = used;
//Serial.print("alloc_f32:");
//Serial.println((uint32_t)block, HEX);
// Serial.print("alloc_f32:"); Serial.println((uint32_t)block, HEX);
return block;
}
@ -106,8 +118,7 @@ void AudioStream_F32::release(audio_block_f32_t *block)
if (block->ref_count > 1) {
block->ref_count--;
} else {
//Serial.print("release_f32:");
//Serial.println((uint32_t)block, HEX);
//Serial.print("release_f32:"); Serial.println((uint32_t)block, HEX);
f32_memory_pool_available_mask[index] |= mask;
f32_memory_used--;
}
@ -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 *in;
//Serial.print(index); Serial.print(" <index RcvReadOnly() num_inputs_f32> "); Serial.println(num_inputs_f32);
if (index >= num_inputs_f32) return NULL;
in = inputQueue_f32[index];
inputQueue_f32[index] = NULL;
return in;
}
// Receive block from an input. The block will not
// be shared, so its contents may be changed.
audio_block_f32_t * AudioStream_F32::receiveWritable_f32(unsigned int index)

@ -17,8 +17,8 @@
#include "AudioMixer_F32.h"
#include "AudioMultiply_F32.h"
#include "AudioSettings_F32.h"
//#include "input_i2s_f32.h"
#include "output_i2s_OA_f32.h"
#include "input_i2s_OA_f32.h"
#include "output_i2s_OA_F32.h"
#include "play_queue_f32.h"
#include "record_queue_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

@ -18,6 +18,12 @@ bool AudioPlayQueue_F32::available(void)
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)
{
if (userblock) return userblock->data;
@ -28,6 +34,13 @@ float32_t * AudioPlayQueue_F32::getBuffer(void)
}
}
/* 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)
{
uint32_t h;
@ -47,9 +60,9 @@ void AudioPlayQueue_F32::update(void)
uint32_t t;
t = tail;
if (t != head) {
if (++t >= 32) t = 0;
block = queue[t];
if (t != head) { // a data block is available to transmit out
if (++t >= 32) t = 0; // tail is advanced by one, circularly
block = queue[t]; // pointer to next block
tail = t;
transmit(block);
release(block);
@ -70,5 +83,4 @@ void AudioPlayQueue_F32::playAudioBlock(audio_block_f32_t *audio_block) {
audio_block->ref_count++; //take ownership of this block
head = h;
//userblock = NULL;
}

@ -5,7 +5,26 @@
* Extended from on Teensy Audio Library
*
* 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_
#define play_queue_f32_h_
@ -25,7 +44,7 @@ public:
//void play(const int16_t *data, uint32_t len);
//void play(float32_t data);
//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);
float32_t * getBuffer(void);
void playBuffer(void);

@ -58,35 +58,24 @@ void AudioSynthGaussian_F32::update(void)
* 2nd ed, with the comment "this is about as good as any 32-bit linear
* congruential generator, entirely adequate for many uses."
*/
// Try:
union {
uint32_t i32;
float32_t f32;
} uinf;
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 - Gets warning
// Try
/* dev += (*(float *)&it) - 1.0f; // Cute convert to float, but gets compiler warning */
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);
@ -98,4 +87,5 @@ void AudioSynthGaussian_F32::update(void)
}
t1 = tElapse;
#endif
}

@ -18,8 +18,7 @@ extern "C" {
extern const int16_t AudioWaveformSine[257];
}
void AudioSynthWaveformSine_F32::update(void)
{
void AudioSynthWaveformSine_F32::update(void) {
audio_block_f32_t *block;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2;
@ -39,11 +38,11 @@ void AudioSynthWaveformSine_F32::update(void)
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
#if (defined(KINETISK) || defined(__IMXRT1062__) )
#if (defined(KINETISK) || defined(__IMXRT1062__) )
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);
#endif
#endif
ph += inc;
block->data[i] = block->data[i] / 32767.0f; // scale to float
}
@ -53,13 +52,7 @@ void AudioSynthWaveformSine_F32::update(void)
AudioStream_F32::release(block);
return;
}
}
phase_accumulator += phase_increment * block_length;
}
}// end if (magnitude)
phase_accumulator += phase_increment * block_length; // continue sine wave while magnitude==0
} // end if (enabled)
}

Loading…
Cancel
Save