|
- #include "AudioStream.h"
- #include "arm_math.h"
-
-
- // When changing multiple audio object settings that must update at
- // the same time, these functions allow the audio library interrupt
- // to be disabled. For example, you may wish to begin playing a note
- // in response to reading an analog sensor. If you have "velocity"
- // information, you might start the sample playing and also adjust
- // the gain of a mixer channel. Use AudioNoInterrupts() first, then
- // make both changes to the 2 separate objects. Then allow the audio
- // library to update with AudioInterrupts(). Both changes will happen
- // at the same time, because AudioNoInterrupts() prevents any updates
- // while you make changes.
- #define AudioNoInterrupts() (NVIC_DISABLE_IRQ(IRQ_SOFTWARE))
- #define AudioInterrupts() (NVIC_ENABLE_IRQ(IRQ_SOFTWARE))
-
- // waveforms.c
- extern "C" {
- extern const int16_t AudioWaveformSine[257];
- extern const int16_t AudioWaveformTriangle[257];
- extern const int16_t AudioWaveformSquare[257];
- extern const int16_t AudioWaveformSawtooth[257];
- }
-
- // windows.c
- extern "C" {
- extern const int16_t AudioWindowHanning256[];
- extern const int16_t AudioWindowBartlett256[];
- extern const int16_t AudioWindowBlackman256[];
- extern const int16_t AudioWindowFlattop256[];
- extern const int16_t AudioWindowBlackmanHarris256[];
- extern const int16_t AudioWindowNuttall256[];
- extern const int16_t AudioWindowBlackmanNuttall256[];
- extern const int16_t AudioWindowWelch256[];
- extern const int16_t AudioWindowHamming256[];
- extern const int16_t AudioWindowCosine256[];
- extern const int16_t AudioWindowTukey256[];
- }
-
- class AudioAnalyzeFFT256 : public AudioStream
- {
- public:
- AudioAnalyzeFFT256(uint8_t navg = 8, const int16_t *win = AudioWindowHanning256)
- : AudioStream(1, inputQueueArray), window(win),
- prevblock(NULL), count(0), naverage(navg), outputflag(false) { init(); }
-
- bool available() {
- if (outputflag == true) {
- outputflag = false;
- return true;
- }
- return false;
- }
- virtual void update(void);
- //uint32_t cycles;
- int32_t output[128] __attribute__ ((aligned (4)));
- private:
- void init(void);
- const int16_t *window;
- audio_block_t *prevblock;
- int16_t buffer[512] __attribute__ ((aligned (4)));
- uint8_t count;
- uint8_t naverage;
- bool outputflag;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
- #ifdef ORIGINAL_AUDIOSYNTHWAVEFORM
- class AudioSynthWaveform : public AudioStream
- {
- public:
- AudioSynthWaveform(const int16_t *waveform)
- : AudioStream(0, NULL), wavetable(waveform), magnitude(0), phase(0)
- , ramp_down(0), ramp_up(0), ramp_mag(0), ramp_length(0)
- { }
- void frequency(float freq) {
- if (freq > AUDIO_SAMPLE_RATE_EXACT / 2 || freq < 0.0) return;
- phase_increment = (freq / AUDIO_SAMPLE_RATE_EXACT) * 4294967296.0f;
- }
- void amplitude(float n) { // 0 to 1.0
- if (n < 0) n = 0;
- else if (n > 1.0) n = 1.0;
- // Ramp code
- if(magnitude && (n == 0)) {
- ramp_down = ramp_length;
- ramp_up = 0;
- last_magnitude = magnitude;
- }
- else if((magnitude == 0) && n) {
- ramp_up = ramp_length;
- ramp_down = 0;
- }
- // set new magnitude
- magnitude = n * 32767.0;
- }
- virtual void update(void);
- void set_ramp_length(uint16_t r_length);
-
- private:
- const int16_t *wavetable;
- uint16_t magnitude;
- uint16_t last_magnitude;
- uint32_t phase;
- uint32_t phase_increment;
- uint32_t ramp_down;
- uint32_t ramp_up;
- uint32_t ramp_mag;
- uint16_t ramp_length;
- };
-
- #else
-
- #define AUDIO_SAMPLE_RATE_ROUNDED (44118)
-
- #define DELAY_PASSTHRU -1
-
- #define TONE_TYPE_SINE 0
- #define TONE_TYPE_SAWTOOTH 1
- #define TONE_TYPE_SQUARE 2
- #define TONE_TYPE_TRIANGLE 3
-
- class AudioSynthWaveform :
- public AudioStream
- {
- public:
- AudioSynthWaveform(void) :
- AudioStream(0,NULL),
- tone_freq(0), tone_phase(0), tone_incr(0), tone_type(0),
- ramp_down(0), ramp_up(0), ramp_length(0)
- {
- }
- // Change the frequency on-the-fly to permit a phase-continuous
- // change between two frequencies.
- void frequency(int t_hi)
- {
- tone_incr = (0x100000000LL*t_hi)/AUDIO_SAMPLE_RATE_EXACT;
- }
- // If ramp_length is non-zero this will set up
- // either a rmap up or a ramp down when a wave
- // first starts or when the amplitude is set
- // back to zero.
- // Note that if the ramp_length is N, the generated
- // wave will be N samples longer than when it is not
- // ramp
- void amplitude(float n) { // 0 to 1.0
- if (n < 0) n = 0;
- else if (n > 1.0) n = 1.0;
- // Ramp code
- if(tone_amp && (n == 0)) {
- ramp_down = ramp_length;
- ramp_up = 0;
- last_tone_amp = tone_amp;
- }
- else if((tone_amp == 0) && n) {
- ramp_up = ramp_length;
- ramp_down = 0;
- // reset the phase when the amplitude was zero
- // and has now been increased. Note that this
- // happens even if the wave is not ramped
- // so that the signal starts at zero
- tone_phase = 0;
- }
- // set new magnitude
- tone_amp = n * 32767.0;
- }
- boolean begin(float t_amp,int t_hi,short t_type);
- virtual void update(void);
- void set_ramp_length(uint16_t r_length);
-
- private:
- short tone_amp;
- short last_tone_amp;
- short tone_freq;
- uint32_t tone_phase;
- uint32_t tone_incr;
- short tone_type;
-
- uint32_t ramp_down;
- uint32_t ramp_up;
- uint16_t ramp_length;
- };
-
- #endif
-
-
-
- #if 0
- class AudioSineWaveMod : public AudioStream
- {
- public:
- AudioSineWaveMod() : AudioStream(1, inputQueueArray) {}
- void frequency(float freq);
- //void amplitude(q15 n);
- virtual void update(void);
- private:
- uint32_t phase;
- uint32_t phase_increment;
- uint32_t modulation_factor;
- audio_block_t *inputQueueArray[1];
- };
- #endif
-
-
-
-
-
- class AudioOutputPWM : public AudioStream
- {
- public:
- AudioOutputPWM(void) : AudioStream(1, inputQueueArray) { begin(); }
- virtual void update(void);
- void begin(void);
- friend void dma_ch3_isr(void);
- private:
- static audio_block_t *block_1st;
- static audio_block_t *block_2nd;
- static uint32_t block_offset;
- static bool update_responsibility;
- static uint8_t interrupt_count;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
-
-
- class AudioOutputAnalog : public AudioStream
- {
- public:
- AudioOutputAnalog(void) : AudioStream(1, inputQueueArray) { begin(); }
- virtual void update(void);
- void begin(void);
- void analogReference(int ref);
- friend void dma_ch4_isr(void);
- private:
- static audio_block_t *block_left_1st;
- static audio_block_t *block_left_2nd;
- static bool update_responsibility;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
-
-
- class AudioPrint : public AudioStream
- {
- public:
- AudioPrint(const char *str) : AudioStream(1, inputQueueArray), name(str) {}
- virtual void update(void);
- private:
- const char *name;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- class AudioInputI2S : public AudioStream
- {
- public:
- AudioInputI2S(void) : AudioStream(0, NULL) { begin(); }
- virtual void update(void);
- void begin(void);
- friend void dma_ch1_isr(void);
- protected:
- AudioInputI2S(int dummy): AudioStream(0, NULL) {} // to be used only inside AudioInputI2Sslave !!
- static bool update_responsibility;
- private:
- static audio_block_t *block_left;
- static audio_block_t *block_right;
- static uint16_t block_offset;
- };
-
-
- class AudioOutputI2S : public AudioStream
- {
- public:
- AudioOutputI2S(void) : AudioStream(2, inputQueueArray) { begin(); }
- virtual void update(void);
- void begin(void);
- friend void dma_ch0_isr(void);
- friend class AudioInputI2S;
- protected:
- AudioOutputI2S(int dummy): AudioStream(2, inputQueueArray) {} // to be used only inside AudioOutputI2Sslave !!
- static void config_i2s(void);
- static audio_block_t *block_left_1st;
- static audio_block_t *block_right_1st;
- static bool update_responsibility;
- private:
- 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_t *inputQueueArray[2];
- };
-
-
- class AudioInputI2Sslave : public AudioInputI2S
- {
- public:
- AudioInputI2Sslave(void) : AudioInputI2S(0) { begin(); }
- void begin(void);
- friend void dma_ch1_isr(void);
- };
-
-
- class AudioOutputI2Sslave : public AudioOutputI2S
- {
- public:
- AudioOutputI2Sslave(void) : AudioOutputI2S(0) { begin(); } ;
- void begin(void);
- friend class AudioInputI2Sslave;
- friend void dma_ch0_isr(void);
- protected:
- static void config_i2s(void);
- };
-
-
-
-
-
- class AudioInputAnalog : public AudioStream
- {
- public:
- AudioInputAnalog(unsigned int pin) : AudioStream(0, NULL) { begin(pin); }
- virtual void update(void);
- void begin(unsigned int pin);
- friend void dma_ch2_isr(void);
- private:
- static audio_block_t *block_left;
- static uint16_t block_offset;
- uint16_t dc_average;
- static bool update_responsibility;
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include "SD.h"
-
- class AudioPlaySDcardWAV : public AudioStream
- {
- public:
- AudioPlaySDcardWAV(void) : AudioStream(0, NULL) { begin(); }
- void begin(void);
-
- bool play(const char *filename);
- void stop(void);
- bool start(void);
- virtual void update(void);
- private:
- File wavfile;
- bool consume(void);
- bool parse_format(void);
- uint32_t header[5];
- uint32_t data_length; // number of bytes remaining in data section
- audio_block_t *block_left;
- audio_block_t *block_right;
- uint16_t block_offset;
- uint8_t buffer[512];
- uint16_t buffer_remaining;
- uint8_t state;
- uint8_t state_play;
- uint8_t leftover_bytes;
- };
-
-
- class AudioPlaySDcardRAW : public AudioStream
- {
- public:
- AudioPlaySDcardRAW(void) : AudioStream(0, NULL) { begin(); }
- void begin(void);
- bool play(const char *filename);
- void stop(void);
- virtual void update(void);
- private:
- File rawfile;
- audio_block_t *block;
- bool playing;
- bool paused;
- };
-
-
-
- class AudioPlayMemory : public AudioStream
- {
- public:
- AudioPlayMemory(void) : AudioStream(0, NULL), playing(0) { }
- void play(const unsigned int *data);
- void stop(void);
- virtual void update(void);
- private:
- const unsigned int *next;
- uint32_t length;
- int16_t prior;
- volatile uint8_t playing;
- };
-
-
-
-
-
-
-
-
-
-
- class AudioMixer4 : public AudioStream
- {
- public:
- AudioMixer4(void) : AudioStream(4, inputQueueArray) {
- for (int i=0; i<4; i++) multiplier[i] = 65536;
- }
- virtual void update(void);
- void gain(unsigned int channel, float gain) {
- if (channel >= 4) return;
- if (gain > 32767.0f) gain = 32767.0f;
- else if (gain < 0.0f) gain = 0.0f;
- multiplier[channel] = gain * 65536.0f; // TODO: proper roundoff?
- }
- private:
- int32_t multiplier[4];
- audio_block_t *inputQueueArray[4];
- };
-
-
-
-
-
-
- class AudioFilterBiquad : public AudioStream
- {
- public:
- AudioFilterBiquad(int *parameters)
- : AudioStream(1, inputQueueArray), definition(parameters) { }
- virtual void update(void);
-
- void updateCoefs(int *source, bool doReset);
- void updateCoefs(int *source);
- private:
- int *definition;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
- class AudioEffectFade : public AudioStream
- {
- public:
- AudioEffectFade(void)
- : AudioStream(1, inputQueueArray), position(0xFFFFFFFF) {}
- void fadeIn(uint32_t milliseconds) {
- uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
- //Serial.printf("fadeIn, %u samples\n", samples);
- fadeBegin(0xFFFFFFFFu / samples, 1);
- }
- void fadeOut(uint32_t milliseconds) {
- uint32_t samples = (uint32_t)(milliseconds * 441u + 5u) / 10u;
- //Serial.printf("fadeOut, %u samples\n", samples);
- fadeBegin(0xFFFFFFFFu / samples, 0);
- }
- virtual void update(void);
- private:
- void fadeBegin(uint32_t newrate, uint8_t dir);
- uint32_t position; // 0 = off, 0xFFFFFFFF = on
- uint32_t rate;
- uint8_t direction; // 0 = fading out, 1 = fading in
- audio_block_t *inputQueueArray[1];
- };
-
-
-
- class AudioAnalyzeToneDetect : public AudioStream
- {
- public:
- AudioAnalyzeToneDetect(void)
- : AudioStream(1, inputQueueArray), thresh(6554), enabled(false) { }
- void frequency(float freq, uint16_t cycles=10) {
- set_params((int32_t)(cos((double)freq
- * (2.0 * 3.14159265358979323846 / AUDIO_SAMPLE_RATE_EXACT))
- * (double)2147483647.999), cycles,
- (float)AUDIO_SAMPLE_RATE_EXACT / freq * (float)cycles + 0.5f);
- }
- void set_params(int32_t coef, uint16_t cycles, uint16_t len);
- bool available(void) {
- __disable_irq();
- bool flag = new_output;
- if (flag) new_output = false;
- __enable_irq();
- return flag;
- }
- float read(void);
- void threshold(float level) {
- if (level < 0.01f) thresh = 655;
- else if (level > 0.99f) thresh = 64881;
- else thresh = level * 65536.0f + 0.5f;
- }
- operator bool(); // true if at or above threshold, false if below
- virtual void update(void);
- private:
- int32_t coefficient; // Goertzel algorithm coefficient
- int32_t s1, s2; // Goertzel algorithm state
- int32_t out1, out2; // Goertzel algorithm state output
- uint16_t length; // number of samples to analyze
- uint16_t count; // how many left to analyze
- uint16_t ncycles; // number of waveform cycles to seek
- uint16_t thresh; // threshold, 655 to 64881 (1% to 99%)
- bool enabled;
- volatile bool new_output;
- audio_block_t *inputQueueArray[1];
- };
-
-
-
-
-
-
-
- // TODO: more audio processing objects....
- // sine wave with frequency modulation (phase)
- // waveforms with bandwidth limited tables for synth
- // envelope: attack-decay-sustain-release, maybe other more complex?
- // MP3 decoding - it is possible with optimized code?
- // other decompression, ADPCM, Vorbis, Speex, etc?
-
-
-
-
- // A base class for all Codecs, DACs and ADCs, so at least the
- // most basic functionality is consistent.
-
- #define AUDIO_INPUT_LINEIN 0
- #define AUDIO_INPUT_MIC 1
-
- class AudioControl
- {
- public:
- virtual bool enable(void) = 0;
- virtual bool disable(void) = 0;
- virtual bool volume(float volume) = 0; // volume 0.0 to 100.0
- virtual bool inputLevel(float volume) = 0; // volume 0.0 to 100.0
- virtual bool inputSelect(int n) = 0;
- };
-
-
-
- class AudioControlWM8731 : public AudioControl
- {
- public:
- bool enable(void);
- bool disable(void) { return false; }
- bool volume(float n) { return volumeInteger(n * 0.8 + 47.499); }
- bool inputLevel(float n) { return false; }
- bool inputSelect(int n) { return false; }
- protected:
- bool write(unsigned int reg, unsigned int val);
- bool volumeInteger(unsigned int n); // range: 0x2F to 0x7F
- };
-
- class AudioControlWM8731master : public AudioControlWM8731
- {
- public:
- bool enable(void);
- };
-
-
- class AudioControlSGTL5000 : public AudioControl
- {
- public:
- bool enable(void);
- bool disable(void) { return false; }
- bool volume(float n) { return volumeInteger(n * 1.29 + 0.499); }
- bool inputLevel(float n) {return false;}
- bool muteHeadphone(void) { return write(0x0024, ana_ctrl | (1<<4)); }
- bool unmuteHeadphone(void) { return write(0x0024, ana_ctrl & ~(1<<4)); }
- bool muteLineout(void) { return write(0x0024, ana_ctrl | (1<<8)); }
- bool unmuteLineout(void) { return write(0x0024, ana_ctrl & ~(1<<8)); }
- bool inputSelect(int n) {
- if (n == AUDIO_INPUT_LINEIN) {
- return write(0x0024, ana_ctrl | (1<<2));
- } else if (n == AUDIO_INPUT_MIC) {
- //return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2));
- return write(0x002A, 0x0173) && write(0x0024, ana_ctrl & ~(1<<2)); // +40dB
- } else {
- return false;
- }
- }
- //bool inputLinein(void) { return write(0x0024, ana_ctrl | (1<<2)); }
- //bool inputMic(void) { return write(0x002A, 0x0172) && write(0x0024, ana_ctrl & ~(1<<2)); }
-
- bool volume(float left, float right);
- unsigned short micGain(unsigned int n) { return modify(0x002A, n&3, 3); }
- unsigned short lo_lvl(uint8_t n);
- unsigned short lo_lvl(uint8_t left, uint8_t right);
- unsigned short dac_vol(float n);
- unsigned short dac_vol(float left, float right);
- unsigned short dap_mix_enable(uint8_t n);
- unsigned short dap_enable(uint8_t n);
- unsigned short dap_enable(void);
- unsigned short dap_peqs(uint8_t n);
- unsigned short dap_audio_eq(uint8_t n);
- unsigned short dap_audio_eq_band(uint8_t bandNum, float n);
- void dap_audio_eq_geq(float bass, float mid_bass, float midrange, float mid_treble, float treble);
- void dap_audio_eq_tone(float bass, float treble);
- void load_peq(uint8_t filterNum, int *filterParameters);
-
-
- protected:
- bool muted;
- bool volumeInteger(unsigned int n); // range: 0x00 to 0x80
- uint16_t ana_ctrl;
-
- unsigned char calcVol(float n, unsigned char range);
-
- unsigned int read(unsigned int reg);
- bool write(unsigned int reg, unsigned int val);
- unsigned int modify(unsigned int reg, unsigned int val, unsigned int iMask);
- };
-
- //For Filter Type: 0 = LPF, 1 = HPF, 2 = BPF, 3 = NOTCH, 4 = PeakingEQ, 5 = LowShelf, 6 = HighShelf
- #define FILTER_LOPASS 0
- #define FILTER_HIPASS 1
- #define FILTER_BANDPASS 2
- #define FILTER_NOTCH 3
- #define FILTER_PARAEQ 4
- #define FILTER_LOSHELF 5
- #define FILTER_HISHELF 6
-
- void calcBiquad(uint8_t filtertype, float fC, float dB_Gain, float Q, uint32_t quantization_unit, uint32_t fS, int *coef);
-
-
-
- /******************************************************************/
-
- // Maximum number of coefficients in a FIR filter
- // The audio breaks up with 128 coefficients so a
- // maximum of 150 is more than sufficient
- #define MAX_COEFFS 150
-
- // Indicates that the code should just pass through the audio
- // without any filtering (as opposed to doing nothing at all)
- #define FIR_PASSTHRU ((short *) 1)
-
- class AudioFilterFIR :
- public AudioStream
- {
- public:
- AudioFilterFIR(void):
- AudioStream(2,inputQueueArray), coeff_p(NULL)
- {
- }
-
- void begin(short *coeff_p,int f_pin);
- virtual void update(void);
- void stop(void);
-
- private:
- audio_block_t *inputQueueArray[2];
- // arm state arrays and FIR instances for left and right channels
- // the state arrays are defined to handle a maximum of MAX_COEFFS
- // coefficients in a filter
- q15_t l_StateQ15[AUDIO_BLOCK_SAMPLES + MAX_COEFFS];
- q15_t r_StateQ15[AUDIO_BLOCK_SAMPLES + MAX_COEFFS];
- arm_fir_instance_q15 l_fir_inst;
- arm_fir_instance_q15 r_fir_inst;
- // pointer to current coefficients or NULL or FIR_PASSTHRU
- short *coeff_p;
- };
-
-
-
- /******************************************************************/
- // A u d i o E f f e c t F l a n g e
- // Written by Pete (El Supremo) Jan 2014
-
- #define DELAY_PASSTHRU 0
-
- class AudioEffectFlange :
- public AudioStream
- {
- public:
- AudioEffectFlange(void):
- AudioStream(2,inputQueueArray) {
- }
-
- boolean begin(short *delayline,int d_length,int delay_offset,int d_depth,float delay_rate);
- boolean modify(int delay_offset,int d_depth,float delay_rate);
- virtual void update(void);
- void stop(void);
-
- private:
- audio_block_t *inputQueueArray[2];
- static short *l_delayline;
- static short *r_delayline;
- static int delay_length;
- static short l_circ_idx;
- static short r_circ_idx;
- static int delay_depth;
- static int delay_offset_idx;
- static int delay_rate_incr;
- static unsigned int l_delay_rate_index;
- static unsigned int r_delay_rate_index;
- };
-
-
- /******************************************************************/
-
- // A u d i o E f f e c t C h o r u s
- // Written by Pete (El Supremo) Jan 2014
-
-
- class AudioEffectChorus :
- public AudioStream
- {
- public:
- AudioEffectChorus(void):
- AudioStream(2,inputQueueArray) {
- }
-
- boolean begin(short *delayline,int delay_length,int n_chorus);
- virtual void update(void);
- void stop(void);
- void modify(int n_chorus);
-
- private:
- audio_block_t *inputQueueArray[2];
- static short *l_delayline;
- static short *r_delayline;
- static short l_circ_idx;
- static short r_circ_idx;
- static int num_chorus;
- static int delay_length;
- };
-
-
- /******************************************************************/
-
- // A u d i o T o n e S w e e p
- // Written by Pete (El Supremo) Feb 2014
-
- class AudioToneSweep : public AudioStream
- {
- public:
- AudioToneSweep(void) :
- AudioStream(0,NULL), sweep_busy(0)
- { }
-
- boolean begin(short t_amp,int t_lo,int t_hi,float t_time);
- virtual void update(void);
- unsigned char busy(void);
-
- private:
- short tone_amp;
- int tone_lo;
- int tone_hi;
- uint64_t tone_freq;
- uint64_t tone_phase;
- uint64_t tone_incr;
- int tone_sign;
- unsigned char sweep_busy;
- };
|