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

pull/11/head
boblark 4 years ago
parent 274108bd7b
commit 89afca0c8f
  1. 65
      AudioEffectCompWDRC_F32.h
  2. 14
      AudioMultiply_F32.h
  3. 36
      AudioSettings_F32.cpp
  4. 64
      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. 96
      play_queue_f32.cpp
  13. 61
      play_queue_f32.h
  14. 76
      synth_GaussianWhiteNoise_F32.cpp
  15. 87
      synth_sine_f32.cpp

@ -1,12 +1,12 @@
/*
* AudioEffectCompWDR_F32: Wide Dynamic Rnage Compressor
*
*
* Created: Chip Audette (OpenAudio) Feb 2017
* Derived From: WDRC_circuit from CHAPRO from BTNRC: https://github.com/BTNRH/chapro
* As of Feb 2017, CHAPRO license is listed as "Creative Commons?"
*
*
* MIT License. Use at your own risk.
*
*
*/
#ifndef _AudioEffectCompWDRC_F32
@ -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);
@ -43,14 +43,14 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
//receive the input audio data
audio_block_f32_t *block = AudioStream_F32::receiveReadOnly_f32();
if (!block) return;
//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);
// transmit the block and release memory
AudioStream_F32::transmit(out_block); // send the FIR output
AudioStream_F32::release(out_block);
@ -59,7 +59,7 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
//here is the function that does all the work
//void cha_agc_channel(float *input, float *output, int cs) {
//void cha_agc_channel(float *input, float *output, int cs) {
// //compress(input, output, cs, &prev_env,
// // CHA_DVAR.alfa, CHA_DVAR.beta, CHA_DVAR.tkgain, CHA_DVAR.tk, CHA_DVAR.cr, CHA_DVAR.bolt, CHA_DVAR.maxdB);
// compress(input, output, cs);
@ -67,22 +67,23 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
//void compress(float *x, float *y, int n, float *prev_env,
// float &alfa, float &beta, float &tkgn, float &tk, float &cr, float &bolt, float &mxdB)
void compress(float *x, float *y, int n)
void compress(float *x, float *y, int n)
//x, input, audio waveform data
//y, output, audio waveform data after compression
//n, input, number of samples in this audio block
{
{
// find smoothed envelope
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);
@ -95,7 +96,7 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
void setDefaultValues(void) {
//set default values...configure as limitter
BTNRH_WDRC::CHA_WDRC gha = {
5.0f, // attack time (ms)
5.0f, // attack time (ms)
50.0f, // release time (ms)
24000.0f, // fs, sampling rate (Hz), THIS IS IGNORED!
115.0f, // maxdB, maximum signal (dB SPL)...assumed SPL for full-scale input signal
@ -120,7 +121,7 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
//set all of the user parameters for the compressor
//assumes that the sample rate has already been set!!!
void setParams(float attack_ms, float release_ms, float maxdB, float tkgain, float comp_ratio, float tk, float bolt) {
//configure the envelope calculator...assumes that the sample rate has already been set!
calcEnvelope.setAttackRelease_msec(attack_ms,release_ms);
@ -133,28 +134,28 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
given_sample_rate_Hz = _fs_Hz;
calcEnvelope.setSampleRate_Hz(_fs_Hz);
}
void setAttackRelease_msec(const float atk_msec, const float rel_msec) {
calcEnvelope.setAttackRelease_msec(atk_msec, rel_msec);
}
void setKneeLimiter_dBSPL(float _bolt) { calcGain.setKneeLimiter_dBSPL(_bolt); }
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 setKneeCompressor_dBSPL(float _tk) { calcGain.setKneeCompressor_dBSPL(_tk); }
void setKneeCompressor_dBFS(float _tk_dBFS) { calcGain.setKneeCompressor_dBFS(_tk_dBFS); }
void setCompRatio(float _cr) { calcGain.setCompRatio(_cr); }
void setMaxdB(float _maxdB) { calcGain.setMaxdB(_maxdB); };
void setAttackRelease_msec(const float atk_msec, const float rel_msec) {
calcEnvelope.setAttackRelease_msec(atk_msec, rel_msec);
}
void setKneeLimiter_dBSPL(float _bolt) { calcGain.setKneeLimiter_dBSPL(_bolt); }
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 setKneeCompressor_dBSPL(float _tk) { calcGain.setKneeCompressor_dBSPL(_tk); }
void setKneeCompressor_dBFS(float _tk_dBFS) { calcGain.setKneeCompressor_dBFS(_tk_dBFS); }
void setCompRatio(float _cr) { calcGain.setCompRatio(_cr); }
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 getGain_dB(void) { return calcGain.getGain_dB(); } //returns the linear gain of the system
float getCurrentGain(void) { return calcGain.getCurrentGain(); }
float getCurrentGain_dB(void) { return calcGain.getCurrentGain_dB(); }
float getGain_dB(void) { return calcGain.getGain_dB(); } //returns the linear gain of the system
float getCurrentGain(void) { return calcGain.getCurrentGain(); }
float getCurrentGain_dB(void) { return calcGain.getCurrentGain_dB(); }
AudioCalcEnvelope_F32 calcEnvelope;
AudioCalcGainWDRC_F32 calcGain;
private:
audio_block_f32_t *inputQueueArray[1];
float given_sample_rate_Hz;
@ -162,4 +163,4 @@ class AudioEffectCompWDRC_F32 : public AudioStream_F32
#endif

@ -1,12 +1,12 @@
/*
* AudioMultiply
*
*
* Created: Patrick Radius, December 2016
* Purpose: Multiply two channels of audio data. Can be used for example as 'vca' or amplitude modulation.
* Assumes floating-point data.
*
* This processes a single stream fo audio data (ie, it is mono)
*
*
* This processes a single stream fo audio data (ie, it is mono)
*
* MIT License. use at your own risk.
*/
#ifndef AUDIOMULTIPLYF32_H
@ -20,10 +20,10 @@ class AudioMultiply_F32 : public AudioStream_F32
//GUI: inputs:2, outputs:1 //this line used for automatic generation of GUI node
public:
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);
private:
audio_block_f32_t *inputQueueArray_f32[2];
};

@ -4,26 +4,26 @@
#include "AudioStream_F32.h"
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))
float foo1 = ((float)(F_CPU / 32))/sample_rate_Hz;
foo1 *= ((float)audio_block_samples);
foo1 /= 100.f;
foo1 += (float)n;
float foo2 = (float)(F_CPU / 16)/sample_rate_Hz;
foo2 *= ((float)audio_block_samples);
foo2 /= 100.f;
return foo1 / foo2;
//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)) 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;
foo1 += (float)n;
float foo2 = (float)(F_CPU / 16)/sample_rate_Hz;
foo2 *= ((float)audio_block_samples);
foo2 /= 100.f;
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) {
return cpu_load_percent(AudioStream::cpu_cycles_total);
float AudioSettings_F32::processorUsage(void) {
return cpu_load_percent(AudioStream::cpu_cycles_total);
};
float AudioSettings_F32::processorUsageMax(void) {
return cpu_load_percent(AudioStream::cpu_cycles_total_max);
float AudioSettings_F32::processorUsageMax(void) {
return cpu_load_percent(AudioStream::cpu_cycles_total_max);
}
void AudioSettings_F32::processorUsageMaxReset(void) {
AudioStream::cpu_cycles_total_max = AudioStream::cpu_cycles_total;
}
void AudioSettings_F32::processorUsageMaxReset(void) {
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;
audio_block_f32_t* allocate_f32_memory(const int num) {
static bool firstTime=true;
static audio_block_f32_t *data_f32;
if (firstTime == true) {
firstTime = false;
data_f32 = new audio_block_f32_t[num];
}
return data_f32;
static bool firstTime=true;
static audio_block_f32_t *data_f32;
if (firstTime == true) {
firstTime = false;
data_f32 = new audio_block_f32_t[num];
}
return data_f32;
}
void AudioMemory_F32(const int num) {
audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num);
audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num);
}
void AudioMemory_F32(const int num, const AudioSettings_F32 &settings) {
audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num, settings);
audio_block_f32_t *data_f32 = allocate_f32_memory(num);
if (data_f32 != NULL) AudioStream_F32::initialize_f32_memory(data_f32, num, settings);
}
// 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;
//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;
}
@ -52,8 +53,8 @@ void AudioStream_F32::initialize_f32_memory(audio_block_f32_t *data, unsigned in
{
initialize_f32_memory(data,num);
for (unsigned int i=0; i < num; i++) {
data[i].fs_Hz = settings.sample_rate_Hz;
data[i].length = settings.audio_block_samples;
data[i].fs_Hz = settings.sample_rate_Hz;
data[i].length = settings.audio_block_samples;
}
} // end initialize_memory
@ -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--;
}
@ -125,17 +136,17 @@ void AudioStream_F32::transmit(audio_block_f32_t *block, unsigned char index)
{
//Serial.print("AudioStream_F32: transmit(). start...index = ");Serial.println(index);
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) {
//Serial.println(" : if1");
//Serial.println(" : if1");
if (c->dst.inputQueue_f32[c->dest_index] == NULL) {
//Serial.println(" : if2");
//Serial.println(" : if2");
c->dst.inputQueue_f32[c->dest_index] = block;
block->ref_count++;
//Serial.print(" : block->ref_count = "); Serial.println(block->ref_count);
}
}
}
}
//Serial.println("AudioStream_F32: transmit(). finished.");
}
@ -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)
@ -172,7 +182,7 @@ audio_block_f32_t * AudioStream_F32::receiveWritable_f32(unsigned int index)
void AudioConnection_F32::connect(void) {
AudioConnection_F32 *p;
if (dest_index > dst.num_inputs_f32) return;
__disable_irq();
p = src.destination_list_f32;

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

@ -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
*
* License: MIT License. Use at your own risk.
* License: MIT License. Use at your own risk.
*/
#include "play_queue_f32.h"
@ -12,63 +12,75 @@
bool AudioPlayQueue_F32::available(void)
{
if (userblock) return true;
userblock = allocate_f32();
if (userblock) return true;
return false;
if (userblock) return true;
userblock = allocate_f32();
if (userblock) return true;
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;
while (1) {
userblock = allocate_f32();
if (userblock) return userblock->data;
yield();
}
if (userblock) return userblock->data;
while (1) {
userblock = allocate_f32();
if (userblock) return userblock->data;
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)
{
uint32_t h;
uint32_t h;
if (!userblock) return;
h = head + 1;
if (h >= 32) h = 0;
while (tail == h) ; // wait until space in the queue
queue[h] = userblock;
head = h;
userblock = NULL;
if (!userblock) return;
h = head + 1;
if (h >= 32) h = 0;
while (tail == h) ; // wait until space in the queue
queue[h] = userblock;
head = h;
userblock = NULL;
}
void AudioPlayQueue_F32::update(void)
{
audio_block_f32_t *block;
uint32_t t;
audio_block_f32_t *block;
uint32_t t;
t = tail;
if (t != head) {
if (++t >= 32) t = 0;
block = queue[t];
tail = t;
transmit(block);
release(block);
}
t = tail;
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);
}
}
//assume user already has an audio_block that was NOT allocated by this
//playBuffer. Here, you hand it your buffer. This object takes ownership
//of it and puts it into the queue
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
*
* 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_
#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
public:
AudioPlayQueue_F32(void) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { }
AudioPlayQueue_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { }
//void play(int16_t data);
//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 *);
bool available(void);
float32_t * getBuffer(void);
void playBuffer(void);
void stop(void);
//bool isPlaying(void) { return playing; }
virtual void update(void);
AudioPlayQueue_F32(void) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { }
AudioPlayQueue_F32(const AudioSettings_F32 &settings) : AudioStream_F32(0, NULL),
userblock(NULL), head(0), tail(0) { }
//void play(int16_t data);
//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 *); // Not in I16 library
bool available(void);
float32_t * getBuffer(void);
void playBuffer(void);
void stop(void);
//bool isPlaying(void) { return playing; }
virtual void update(void);
private:
audio_block_f32_t *queue[32];
audio_block_f32_t *userblock;
volatile uint8_t head, tail;
audio_block_f32_t *queue[32];
audio_block_f32_t *userblock;
volatile uint8_t head, tail;
};
#endif

@ -1,9 +1,9 @@
/*
* synth_GaussianWhiteNoise_F32.cpp
* by Bob Larkin W7PUA 15 June 2020
*
* Created: Chip Audette, OpenAudio, Feb 2017
*
* Created: Chip Audette, OpenAudio, Feb 2017
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -32,25 +32,25 @@
void AudioSynthGaussian_F32::update(void)
{
audio_block_f32_t *blockOut;
uint32_t it;
float32_t rdev = 0.0f;
audio_block_f32_t *blockOut;
uint32_t it;
float32_t rdev = 0.0f;
float32_t* pd;
if (sd < 0.01f) {
return; // Not enabled
}
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;
}
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
@ -58,44 +58,34 @@ 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 {
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
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);
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
/* 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);
#if TEST_TIME_GWN
t2 = tElapse;
if(iitt++ < 0) {
Serial.print("At Gaussian Noise end, microseconds = ");
Serial.println (t2 - t1);
Serial.print("At Gaussian Noise end, microseconds = ");
Serial.println (t2 - t1);
}
t1 = tElapse;
#endif
}

@ -1,9 +1,9 @@
/*
/*
* AudioSynthWaveformSine_F32
*
*
* Created: Chip Audette (OpenAudio) Feb 2017
* Modeled on: AudioSynthWaveformSine from Teensy Audio Library
*
*
* Purpose: Create sine wave of given amplitude and frequency
*
* License: MIT License. Use at your own risk.
@ -18,48 +18,41 @@ extern "C" {
extern const int16_t AudioWaveformSine[257];
}
void AudioSynthWaveformSine_F32::update(void)
{
audio_block_f32_t *block;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2;
static uint32_t block_length = 0;
if (enabled) {
if (magnitude) {
block = allocate_f32();
if (block) {
block_length = (uint32_t)block->length;
ph = phase_accumulator;
inc = phase_increment;
for (i=0; i < block_length; i++) {
index = ph >> 24;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
#if (defined(KINETISK) || defined(__IMXRT1062__) )
block->data[i] = (float) multiply_32x32_rshift32(val1 + val2, magnitude);
#elif defined(KINETISL)
block->data[i] = (float) ((((val1 + val2) >> 16) * magnitude) >> 16);
#endif
ph += inc;
block->data[i] = block->data[i] / 32767.0f; // scale to float
}
phase_accumulator = ph;
AudioStream_F32::transmit(block);
AudioStream_F32::release(block);
return;
}
}
phase_accumulator += phase_increment * block_length;
}
void AudioSynthWaveformSine_F32::update(void) {
audio_block_f32_t *block;
uint32_t i, ph, inc, index, scale;
int32_t val1, val2;
static uint32_t block_length = 0;
if (enabled) {
if (magnitude) {
block = allocate_f32();
if (block) {
block_length = (uint32_t)block->length;
ph = phase_accumulator;
inc = phase_increment;
for (i=0; i < block_length; i++) {
index = ph >> 24;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
#if (defined(KINETISK) || defined(__IMXRT1062__) )
block->data[i] = (float) multiply_32x32_rshift32(val1 + val2, magnitude);
#elif defined(KINETISL)
block->data[i] = (float) ((((val1 + val2) >> 16) * magnitude) >> 16);
#endif
ph += inc;
block->data[i] = block->data[i] / 32767.0f; // scale to float
}
phase_accumulator = ph;
AudioStream_F32::transmit(block);
AudioStream_F32::release(block);
return;
}
}// end if (magnitude)
phase_accumulator += phase_increment * block_length; // continue sine wave while magnitude==0
} // end if (enabled)
}

Loading…
Cancel
Save