Selaa lähdekoodia

Reformat AudioSynthWaveform (no actual code change)

dds
PaulStoffregen 6 vuotta sitten
vanhempi
commit
99b0e1a44c
2 muutettua tiedostoa jossa 210 lisäystä ja 206 poistoa
  1. +130
    -128
      synth_waveform.cpp
  2. +80
    -78
      synth_waveform.h

+ 130
- 128
synth_waveform.cpp Näytä tiedosto

@@ -1,5 +1,5 @@
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
* Copyright (c) 2018, 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
@@ -39,136 +39,138 @@

void AudioSynthWaveform::update(void)
{
audio_block_t *block;
short *bp, *end;
int32_t val1, val2, val3;
uint32_t index, scale;
// temporaries for TRIANGLE
uint32_t mag;
short tmp_amp;
if(tone_amp == 0) return;
block = allocate();
if (block) {
bp = block->data;
switch(tone_type) {
case WAVEFORM_SINE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
// Calculate interpolated sin
index = tone_phase >> 23;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (tone_phase >> 7) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
// If tone_phase has overflowed, truncate the top bit
if(tone_phase & 0x80000000)tone_phase &= 0x7fffffff;
}
break;

case WAVEFORM_ARBITRARY:
if (!arbdata) {
release(block);
audio_block_t *block;
short *bp, *end;
int32_t val1, val2, val3;
uint32_t index, scale;
uint32_t mag;
short tmp_amp;

if (tone_amp == 0) return;
block = allocate();
if (!block) {
return;
}
// len = 256
for (int i = 0; i < AUDIO_BLOCK_SAMPLES;i++) {
index = tone_phase >> 23;
val1 = *(arbdata + index);
val2 = *(arbdata + ((index + 1) & 255));
scale = (tone_phase >> 7) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);
tone_phase += tone_incr;
tone_phase &= 0x7fffffff;
}
break;
case WAVEFORM_SQUARE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x40000000)*bp++ = -tone_amp;
else *bp++ = tone_amp;
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
}
break;
case WAVEFORM_SAWTOOTH:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
*bp++ = ((short)(tone_phase>>15)*tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
}
break;

case WAVEFORM_SAWTOOTH_REVERSE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
*bp++ = ((short)(tone_phase>>15)*tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase -= tone_incr;
}
break;

case WAVEFORM_TRIANGLE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase & 0x80000000) {
// negative half-cycle
tmp_amp = -tone_amp;
}
else {
// positive half-cycle
tmp_amp = tone_amp;
}
mag = tone_phase << 2;
// Determine which quadrant
if(tone_phase & 0x40000000) {
// negate the magnitude
mag = ~mag + 1;
}
*bp++ = ((short)(mag>>17)*tmp_amp) >> 15;
tone_phase += 2*tone_incr;
}
break;
case WAVEFORM_PULSE:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase < tone_width)*bp++ = -tone_amp;
else *bp++ = tone_amp;
tone_phase += tone_incr;
}
break;
case WAVEFORM_SAMPLE_HOLD:
for(int i = 0;i < AUDIO_BLOCK_SAMPLES;i++) {
if(tone_phase < tone_incr) {
sample = random(-tone_amp, tone_amp);
}
*bp++ = sample;
tone_phase += tone_incr;
}
break;
}
if (tone_offset) {
}
bp = block->data;
end = bp + AUDIO_BLOCK_SAMPLES;
do {
val1 = *bp;
*bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
} while (bp < end);
}
transmit(block,0);
release(block);
}
}
switch(tone_type) {
case WAVEFORM_SINE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
// Calculate interpolated sin
index = tone_phase >> 23;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (tone_phase >> 7) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);

// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
// If tone_phase has overflowed, truncate the top bit
if (tone_phase & 0x80000000) tone_phase &= 0x7fffffff;
}
break;

case WAVEFORM_ARBITRARY:
if (!arbdata) {
release(block);
return;
}
// len = 256
for (int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
index = tone_phase >> 23;
val1 = *(arbdata + index);
val2 = *(arbdata + ((index + 1) & 255));
scale = (tone_phase >> 7) & 0xFFFF;
val2 *= scale;
val1 *= 0xFFFF - scale;
val3 = (val1 + val2) >> 16;
*bp++ = (short)((val3 * tone_amp) >> 15);
tone_phase += tone_incr;
tone_phase &= 0x7fffffff;
}
break;

case WAVEFORM_SQUARE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase & 0x40000000) {
*bp++ = -tone_amp;
} else {
*bp++ = tone_amp;
}
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
}
break;

case WAVEFORM_SAWTOOTH:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = ((short)(tone_phase>>15) * tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase += tone_incr;
}
break;

case WAVEFORM_SAWTOOTH_REVERSE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = ((short)(tone_phase>>15) * tone_amp) >> 15;
// phase and incr are both unsigned 32-bit fractions
tone_phase -= tone_incr;
}
break;

case WAVEFORM_TRIANGLE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase & 0x80000000) {
// negative half-cycle
tmp_amp = -tone_amp;
} else {
// positive half-cycle
tmp_amp = tone_amp;
}
mag = tone_phase << 2;
// Determine which quadrant
if (tone_phase & 0x40000000) {
// negate the magnitude
mag = ~mag + 1;
}
*bp++ = ((short)(mag>>17) * tmp_amp) >> 15;
tone_phase += tone_incr * 2;
}
break;

case WAVEFORM_PULSE:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase < tone_width) {
*bp++ = -tone_amp;
} else {
*bp++ = tone_amp;
}
tone_phase += tone_incr;
}
break;

case WAVEFORM_SAMPLE_HOLD:
for(int i = 0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (tone_phase < tone_incr) {
sample = random(-tone_amp, tone_amp);
}
*bp++ = sample;
tone_phase += tone_incr;
}
break;
}
if (tone_offset) {
bp = block->data;
end = bp + AUDIO_BLOCK_SAMPLES;
do {
val1 = *bp;
*bp++ = signed_saturate_rshift(val1 + tone_offset, 16, 0);
} while (bp < end);
}
transmit(block, 0);
release(block);
}



+ 80
- 78
synth_waveform.h Näytä tiedosto

@@ -27,7 +27,7 @@
#ifndef synth_waveform_h_
#define synth_waveform_h_

#include "Arduino.h"
#include <Arduino.h>
#include "AudioStream.h"
#include "arm_math.h"

@@ -36,9 +36,6 @@ extern "C" {
extern const int16_t AudioWaveformSine[257];
}

#define AUDIO_SAMPLE_RATE_ROUNDED (44118)

#define DELAY_PASSTHRU -1

#define WAVEFORM_SINE 0
#define WAVEFORM_SAWTOOTH 1
@@ -49,84 +46,89 @@ extern const int16_t AudioWaveformSine[257];
#define WAVEFORM_SAWTOOTH_REVERSE 6
#define WAVEFORM_SAMPLE_HOLD 7

// todo: remove these...
#define TONE_TYPE_SINE 0
#define TONE_TYPE_SAWTOOTH 1
#define TONE_TYPE_SQUARE 2
#define TONE_TYPE_TRIANGLE 3

class AudioSynthWaveform :
public AudioStream
class AudioSynthWaveform : public AudioStream
{
public:
AudioSynthWaveform(void) :
AudioStream(0,NULL), tone_amp(0), tone_freq(0),
tone_phase(0), tone_width(0.25), tone_incr(0), tone_type(0),
tone_offset(0), arbdata(NULL)
{
}
void frequency(float t_freq) {
if (t_freq < 0.0) t_freq = 0.0;
else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) t_freq = AUDIO_SAMPLE_RATE_EXACT / 2;
tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
}
void phase(float angle) {
if (angle < 0.0) angle = 0.0;
else if (angle > 360.0) {
angle = angle - 360.0;
if (angle >= 360.0) return;
}
tone_phase = angle * (2147483648.0 / 360.0);
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
if ((tone_amp == 0) && n) {
// reset the phase when the amplitude was zero
// and has now been increased.
tone_phase = 0;
}
// set new magnitude
tone_amp = n * 32767.0;
}
void offset(float n) {
if (n < -1.0) n = -1.0;
else if (n > 1.0) n = 1.0;
tone_offset = n * 32767.0;
}
void pulseWidth(float n) { // 0.0 to 1.0
if (n < 0) n = 0;
else if (n > 1.0) n = 1.0;
tone_width = n * 0x7fffffffLL;
// pulse width is stored as the equivalent phase
}
void begin(short t_type) {
tone_phase = 0;
tone_type = t_type;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
begin(t_type);
}
void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data;
}
virtual void update(void);
AudioSynthWaveform(void) : AudioStream(0,NULL), tone_amp(0), tone_freq(0),
tone_phase(0), tone_width(0.25), tone_incr(0), tone_type(0),
tone_offset(0), arbdata(NULL) {
}

void frequency(float t_freq) {
if (t_freq < 0.0) {
t_freq = 0.0;
} else if (t_freq > AUDIO_SAMPLE_RATE_EXACT / 2) {
t_freq = AUDIO_SAMPLE_RATE_EXACT / 2;
}
tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
}
void phase(float angle) {
if (angle < 0.0) {
angle = 0.0;
} else if (angle > 360.0) {
angle = angle - 360.0;
if (angle >= 360.0) return;
}
tone_phase = angle * (2147483648.0 / 360.0);
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) {
n = 0;
} else if (n > 1.0) {
n = 1.0;
}
if ((tone_amp == 0) && n) {
// reset the phase when the amplitude was zero
// and has now been increased.
tone_phase = 0;
}
// set new magnitude
tone_amp = n * 32767.0;
}
void offset(float n) {
if (n < -1.0) {
n = -1.0;
} else if (n > 1.0) {
n = 1.0;
}
tone_offset = n * 32767.0;
}
void pulseWidth(float n) { // 0.0 to 1.0
if (n < 0) {
n = 0;
} else if (n > 1.0) {
n = 1.0;
}
tone_width = n * 0x7fffffffLL;
// pulse width is stored as the equivalent phase
}
void begin(short t_type) {
tone_phase = 0;
tone_type = t_type;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
begin(t_type);
}
void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data;
}
virtual void update(void);

private:
short tone_amp;
short tone_freq;
uint32_t tone_phase;
uint32_t tone_width;
// sample for SAMPLE_HOLD
short sample;
// volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr;
short tone_type;
int16_t tone_offset;
const int16_t *arbdata;
short tone_amp;
short tone_freq;
uint32_t tone_phase;
uint32_t tone_width;
// sample for SAMPLE_HOLD
short sample;
// volatile prevents the compiler optimizing out the frequency function
volatile uint32_t tone_incr;
short tone_type;
int16_t tone_offset;
const int16_t *arbdata;
};



Loading…
Peruuta
Tallenna