浏览代码

Add AudioSynthWaveformModulated

dds
PaulStoffregen 7 年前
父节点
当前提交
e2db4871c6
共有 4 个文件被更改,包括 287 次插入1 次删除
  1. +1
    -0
      gui/index.html
  2. +3
    -0
      keywords.txt
  3. +204
    -0
      synth_waveform.cpp
  4. +79
    -1
      synth_waveform.h

+ 1
- 0
gui/index.html 查看文件

{"type":"AudioSynthWaveformSineHires","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine_hires","inputs":0,"outputs":2,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthWaveformSineHires","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine_hires","inputs":0,"outputs":2,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthWaveformSineModulated","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine_fm","inputs":1,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthWaveformSineModulated","data":{"defaults":{"name":{"value":"new"}},"shortName":"sine_fm","inputs":1,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthWaveform","data":{"defaults":{"name":{"value":"new"}},"shortName":"waveform","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthWaveform","data":{"defaults":{"name":{"value":"new"}},"shortName":"waveform","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthWaveformModulated","data":{"defaults":{"name":{"value":"new"}},"shortName":"waveform","inputs":2,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthWaveformPWM","data":{"defaults":{"name":{"value":"new"}},"shortName":"pwm","inputs":1,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthWaveformPWM","data":{"defaults":{"name":{"value":"new"}},"shortName":"pwm","inputs":1,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthToneSweep","data":{"defaults":{"name":{"value":"new"}},"shortName":"tonesweep","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthToneSweep","data":{"defaults":{"name":{"value":"new"}},"shortName":"tonesweep","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},
{"type":"AudioSynthWaveformDc","data":{"defaults":{"name":{"value":"new"}},"shortName":"dc","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}}, {"type":"AudioSynthWaveformDc","data":{"defaults":{"name":{"value":"new"}},"shortName":"dc","inputs":0,"outputs":1,"category":"synth-function","color":"#E6E0F8","icon":"arrow-in.png"}},

+ 3
- 0
keywords.txt 查看文件

AudioRecordQueue KEYWORD2 AudioRecordQueue KEYWORD2
AudioSynthToneSweep KEYWORD2 AudioSynthToneSweep KEYWORD2
AudioSynthWaveform KEYWORD2 AudioSynthWaveform KEYWORD2
AudioSynthWaveformModulated KEYWORD2
AudioSynthWaveformSine KEYWORD2 AudioSynthWaveformSine KEYWORD2
AudioSynthWaveformSineHires KEYWORD2 AudioSynthWaveformSineHires KEYWORD2
AudioSynthWaveformSineModulated KEYWORD2 AudioSynthWaveformSineModulated KEYWORD2
secondMix KEYWORD2 secondMix KEYWORD2
pitchMod KEYWORD2 pitchMod KEYWORD2
shape KEYWORD2 shape KEYWORD2
frequencyModulation KEYWORD2
phaseModulation KEYWORD2


AudioMemoryUsage KEYWORD2 AudioMemoryUsage KEYWORD2
AudioMemoryUsageMax KEYWORD2 AudioMemoryUsageMax KEYWORD2

+ 204
- 0
synth_waveform.cpp 查看文件

release(block); release(block);
} }


//--------------------------------------------------------------------------------

void AudioSynthWaveformModulated::update(void)
{
audio_block_t *block, *moddata, *shapedata;
int16_t *bp, *end;
int32_t val1, val2;
int16_t magnitude15;
uint32_t i, ph, index, index2, scale, priorphase;
const uint32_t inc = phase_increment;

moddata = receiveReadOnly(0);
shapedata = receiveReadOnly(1);

ph = phase_accumulator;
priorphase = phasedata[AUDIO_BLOCK_SAMPLES-1];
if (moddata && modulation_type == 0) {
// Frequency Modulation
bp = moddata->data;
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
int32_t n = (*bp++) * modulation_factor; // n is # of octaves to mod
int32_t ipart = n >> 27; // 4 integer bits
n &= 0x7FFFFFF; // 27 fractional bits
#ifdef IMPROVE_EXPONENTIAL_ACCURACY
// exp2 polynomial suggested by Stefan Stenzel on "music-dsp"
// mail list, Wed, 3 Sep 2014 10:08:55 +0200
int32_t x = n << 3;
n = multiply_accumulate_32x32_rshift32_rounded(536870912, x, 1494202713);
int32_t sq = multiply_32x32_rshift32_rounded(x, x);
n = multiply_accumulate_32x32_rshift32_rounded(n, sq, 1934101615);
n = n + (multiply_32x32_rshift32_rounded(sq,
multiply_32x32_rshift32_rounded(x, 1358044250)) << 1);
#else
// exp2 algorithm by Laurent de Soras
// http://www.musicdsp.org/showone.php?id=106
n = (n + 134217728) << 3;
n = multiply_32x32_rshift32_rounded(n, n);
n = multiply_32x32_rshift32_rounded(n, 715827883) << 3;
n = n + 715827882;
#endif
uint32_t scale = n >> (14 - ipart);
uint32_t phinc = ((uint64_t)inc * scale) >> 16; // TODO: saturate 31 bits??
ph += phinc;
phasedata[i] = ph;
}
release(moddata);
} else if (moddata) {
// Phase Modulation

// TODO.....

release(moddata);
} else {
// No Modulation Input
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
phasedata[i] = ph;
ph += inc;
}
}
phase_accumulator = ph;

if (magnitude == 0) {
if (shapedata) release(shapedata);
return;
}
block = allocate();
if (!block) {
if (shapedata) release(shapedata);
return;
}
bp = block->data;

switch(tone_type) {
case WAVEFORM_SINE:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
ph = phasedata[i];
index = ph >> 24;
val1 = AudioWaveformSine[index];
val2 = AudioWaveformSine[index+1];
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
}
break;

case WAVEFORM_ARBITRARY:
if (!arbdata) {
release(block);
if (shapedata) release(shapedata);
return;
}
// len = 256
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
ph = phasedata[i];
index = ph >> 24;
index2 = index + 1;
if (index2 >= 256) index2 = 0;
val1 = *(arbdata + index);
val2 = *(arbdata + index2);
scale = (ph >> 8) & 0xFFFF;
val2 *= scale;
val1 *= 0x10000 - scale;
*bp++ = multiply_32x32_rshift32(val1 + val2, magnitude);
}
break;

case WAVEFORM_PULSE:
if (shapedata) {
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
uint32_t width = ((shapedata->data[i] + 0x8000) & 0xFFFF) << 16;
if (phasedata[i] < width) {
*bp++ = magnitude15;
} else {
*bp++ = -magnitude15;
}
}
break;
} // else fall through to orginary square without shape modulation

case WAVEFORM_SQUARE:
magnitude15 = signed_saturate_rshift(magnitude, 16, 1);
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
if (phasedata[i] & 0x80000000) {
*bp++ = -magnitude15;
} else {
*bp++ = magnitude15;
}
}
break;

case WAVEFORM_SAWTOOTH:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(magnitude, phasedata[i]);
}
break;

case WAVEFORM_SAWTOOTH_REVERSE:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*bp++ = signed_multiply_32x16t(0xFFFFFFFFu - magnitude, phasedata[i]);
}
break;

case WAVEFORM_TRIANGLE_VARIABLE:
if (shapedata) {
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
uint32_t width = (shapedata->data[i] + 0x8000) & 0xFFFF;
uint32_t rise = 0xFFFFFFFF / width;
uint32_t fall = 0xFFFFFFFF / (0xFFFF - width);
width = width << 15;
uint32_t n;
ph = phasedata[i];
if (ph < width) {
n = (ph >> 16) * rise;
*bp++ = ((n >> 16) * magnitude) >> 16;
} else if (ph < 0xFFFFFFFF - width) {
n = 0x7FFFFFFF - (((ph - width) >> 16) * fall);
*bp++ = ((n >> 16) * magnitude) >> 16;
} else {
n = ((ph + width) >> 16) * rise + 0x80000000;
*bp++ = ((n >> 16) * magnitude) >> 16;
}
ph += inc;
}
break;
} // else fall through to orginary triangle without shape modulation

case WAVEFORM_TRIANGLE:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
ph = phasedata[i];
uint32_t phtop = ph >> 30;
if (phtop == 1 || phtop == 2) {
*bp++ = ((0xFFFF - (ph >> 15)) * magnitude) >> 16;
} else {
*bp++ = ((ph >> 15) * magnitude) >> 16;
}
}
break;
case WAVEFORM_SAMPLE_HOLD:
for (i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
ph = phasedata[i];
if (ph < priorphase) {
sample = random(magnitude) - (magnitude >> 1);
}
priorphase = ph;
*bp++ = sample;
}
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);
}
if (shapedata) release(shapedata);
transmit(block, 0);
release(block);
}




+ 79
- 1
synth_waveform.h 查看文件

freq = AUDIO_SAMPLE_RATE_EXACT / 2; freq = AUDIO_SAMPLE_RATE_EXACT / 2;
} }
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT); phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
//tone_incr = (t_freq * (0x80000000LL/AUDIO_SAMPLE_RATE_EXACT)) + 0.5;
} }
void phase(float angle) { void phase(float angle) {
if (angle < 0.0) { if (angle < 0.0) {
}; };




class AudioSynthWaveformModulated : public AudioStream
{
public:
AudioSynthWaveformModulated(void) : AudioStream(2, inputQueueArray),
phase_accumulator(0), phase_increment(0), modulation_factor(32768),
magnitude(0), arbdata(NULL), priorphase(0), sample(0), tone_offset(0),
tone_type(WAVEFORM_SINE), modulation_type(0) {
}

void frequency(float freq) {
if (freq < 0.0) {
freq = 0.0;
} else if (freq > AUDIO_SAMPLE_RATE_EXACT / 2) {
freq = AUDIO_SAMPLE_RATE_EXACT / 2;
}
phase_increment = freq * (4294967296.0 / AUDIO_SAMPLE_RATE_EXACT);
}
void amplitude(float n) { // 0 to 1.0
if (n < 0) {
n = 0;
} else if (n > 1.0) {
n = 1.0;
}
magnitude = n * 65536.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 begin(short t_type) {
tone_type = t_type;
}
void begin(float t_amp, float t_freq, short t_type) {
amplitude(t_amp);
frequency(t_freq);
tone_type = t_type;
}
void arbitraryWaveform(const int16_t *data, float maxFreq) {
arbdata = data;
}
void frequencyModulation(float octaves) {
if (octaves > 12.0) {
octaves = 12.0;
} else if (octaves < 0.1) {
octaves = 0.1;
}
modulation_factor = octaves * 4096.0;
modulation_type = 0;
}
void phaseModulation(float degrees) {
if (degrees > 18000.0) {
degrees = 18000.0;
} else if (degrees < 30.0) {
degrees = 30.0;
}
modulation_factor = degrees * (65536.0 / 360.0);
modulation_type = 1;
}
virtual void update(void);

private:
audio_block_t *inputQueueArray[2];
uint32_t phase_accumulator;
uint32_t phase_increment;
uint32_t modulation_factor;
int32_t magnitude;
const int16_t *arbdata;
uint32_t phasedata[AUDIO_BLOCK_SAMPLES];
uint32_t priorphase;
int16_t sample; // for WAVEFORM_SAMPLE_HOLD
int16_t tone_offset;
uint8_t tone_type;
uint8_t modulation_type;
};



#endif #endif

正在加载...
取消
保存