Merge pull request #10036 from jepler/audiosample-better-properties
audio: reduce code size
This commit is contained in:
commit
9e084176f1
52 changed files with 388 additions and 835 deletions
|
|
@ -251,7 +251,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma,
|
|||
}
|
||||
|
||||
|
||||
if (audiosample_bits_per_sample(sample) == 16) {
|
||||
if (audiosample_get_bits_per_sample(sample) == 16) {
|
||||
dma->beat_size = 2;
|
||||
dma->bytes_per_sample = 2;
|
||||
} else {
|
||||
|
|
@ -262,7 +262,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma,
|
|||
}
|
||||
}
|
||||
// Transfer both channels at once.
|
||||
if (!single_channel_output && audiosample_channel_count(sample) == 2) {
|
||||
if (!single_channel_output && audiosample_get_channel_count(sample) == 2) {
|
||||
dma->beat_size *= 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "py/obj.h"
|
||||
#include "shared-module/audiocore/RawSample.h"
|
||||
#include "shared-module/audiocore/WaveFile.h"
|
||||
#include "shared-module/audiocore/__init__.h"
|
||||
#include "supervisor/background_callback.h"
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -40,10 +41,6 @@ typedef enum {
|
|||
AUDIO_DMA_MEMORY_ERROR,
|
||||
} audio_dma_result;
|
||||
|
||||
uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
|
||||
uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
|
||||
uint8_t audiosample_channel_count(mp_obj_t sample_obj);
|
||||
|
||||
void audio_dma_init(audio_dma_t *dma);
|
||||
void audio_dma_reset(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -216,10 +216,10 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
mp_raise_RuntimeError(MP_ERROR_TEXT("Clock unit in use"));
|
||||
}
|
||||
#endif
|
||||
uint8_t bits_per_sample = audiosample_bits_per_sample(sample);
|
||||
uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample);
|
||||
// We always output stereo so output twice as many bits.
|
||||
uint16_t bits_per_sample_output = bits_per_sample * 2;
|
||||
uint16_t divisor = 48000000 / (bits_per_sample_output * audiosample_sample_rate(sample));
|
||||
uint16_t divisor = 48000000 / (bits_per_sample_output * audiosample_get_sample_rate(sample));
|
||||
// Find a free GCLK to generate the MCLK signal.
|
||||
uint8_t gclk = find_free_gclk(divisor);
|
||||
if (gclk > GCLK_GEN_NUM) {
|
||||
|
|
@ -235,7 +235,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
} else {
|
||||
clkctrl |= I2S_CLKCTRL_FSOUTINV | I2S_CLKCTRL_BITDELAY_I2S;
|
||||
}
|
||||
uint8_t channel_count = audiosample_channel_count(sample);
|
||||
uint8_t channel_count = audiosample_get_channel_count(sample);
|
||||
if (channel_count > 2) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample"));
|
||||
}
|
||||
|
|
@ -245,7 +245,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
#ifdef SAM_D5X_E5X
|
||||
uint32_t serctrl = (self->clock_unit << I2S_RXCTRL_CLKSEL_Pos) | I2S_TXCTRL_TXSAME_SAME;
|
||||
#endif
|
||||
if (audiosample_channel_count(sample) == 1) {
|
||||
if (audiosample_get_channel_count(sample) == 1) {
|
||||
serctrl |= SERCTRL(MONO_MONO);
|
||||
} else {
|
||||
serctrl |= SERCTRL(MONO_STEREO);
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
|
|||
common_hal_audioio_audioout_stop(self);
|
||||
}
|
||||
audio_dma_result result = AUDIO_DMA_OK;
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
#ifdef SAMD21
|
||||
const uint32_t max_sample_rate = 350000;
|
||||
#endif
|
||||
|
|
@ -364,12 +364,12 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
|
|||
right_channel_reg = (uint32_t)&DAC->DATABUF[0].reg;
|
||||
}
|
||||
|
||||
size_t num_channels = audiosample_channel_count(sample);
|
||||
size_t num_channels = audiosample_get_channel_count(sample);
|
||||
|
||||
if (num_channels == 2 &&
|
||||
// Are DAC channels sequential?
|
||||
left_channel_reg + 2 == right_channel_reg &&
|
||||
audiosample_bits_per_sample(sample) == 16) {
|
||||
audiosample_get_bits_per_sample(sample) == 16) {
|
||||
result = audio_dma_setup_playback(&self->left_dma, sample, loop, false, 0,
|
||||
false /* output unsigned */,
|
||||
left_channel_reg,
|
||||
|
|
@ -403,7 +403,7 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
|
|||
}
|
||||
}
|
||||
Tc *timer = tc_insts[self->tc_index];
|
||||
set_timer_frequency(timer, audiosample_sample_rate(sample));
|
||||
set_timer_frequency(timer, audiosample_get_sample_rate(sample));
|
||||
timer->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER;
|
||||
while (timer->COUNT16.STATUS.bit.STOP == 1) {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@ void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) {
|
|||
port_i2s_pause(self);
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
|
||||
self->channel_count = audiosample_channel_count(sample);
|
||||
self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8;
|
||||
self->channel_count = audiosample_get_channel_count(sample);
|
||||
bool single_buffer;
|
||||
bool samples_signed;
|
||||
uint32_t max_buffer_length;
|
||||
|
|
@ -164,7 +164,7 @@ void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) {
|
|||
|
||||
audiosample_reset_buffer(self->sample, false, 0);
|
||||
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
i2s_std_clk_config_t clk_config = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate);
|
||||
CHECK_ESP_RESULT(i2s_channel_reconfig_std_clock(self->handle, &clk_config));
|
||||
|
||||
|
|
|
|||
|
|
@ -595,7 +595,7 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
|
|||
|
||||
self->sample = sample;
|
||||
self->looping = loop;
|
||||
freq_hz = audiosample_sample_rate(self->sample);
|
||||
freq_hz = audiosample_get_sample_rate(self->sample);
|
||||
|
||||
if (freq_hz != self->freq_hz) {
|
||||
common_hal_audioio_audioout_deinit(self);
|
||||
|
|
@ -603,8 +603,8 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self,
|
|||
audioout_init(self);
|
||||
}
|
||||
|
||||
samples_size = audiosample_bits_per_sample(self->sample);
|
||||
channel_count = audiosample_channel_count(self->sample);
|
||||
samples_size = audiosample_get_bits_per_sample(self->sample);
|
||||
channel_count = audiosample_get_channel_count(self->sample);
|
||||
audiosample_get_buffer_structure(self->sample, false,
|
||||
&_single_buffer, &samples_signed,
|
||||
&_max_buffer_length, &_spacing);
|
||||
|
|
|
|||
|
|
@ -337,6 +337,3 @@ USB_NUM_IN_ENDPOINTS = 5
|
|||
|
||||
# Usually lots of flash space available
|
||||
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 1
|
||||
|
||||
CIRCUITPY_AUDIOMP3 ?= 1
|
||||
CIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR ?= 1
|
||||
|
|
|
|||
|
|
@ -374,11 +374,11 @@ static void set_sai_clocking_for_sample_rate(uint32_t sample_rate) {
|
|||
void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) {
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
|
||||
self->channel_count = audiosample_channel_count(sample);
|
||||
self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8;
|
||||
self->channel_count = audiosample_get_channel_count(sample);
|
||||
int instance = SAI_GetInstance(self->peripheral);
|
||||
i2s_playing |= (1 << instance);
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
if (sample_rate != self->sample_rate) {
|
||||
if (__builtin_popcount(i2s_playing) <= 1) {
|
||||
// as this is the first/only i2s instance playing audio, we can
|
||||
|
|
|
|||
|
|
@ -240,8 +240,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8;
|
||||
|
||||
uint32_t max_buffer_length;
|
||||
bool single_buffer, samples_signed;
|
||||
|
|
|
|||
|
|
@ -223,15 +223,15 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
|
|||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8;
|
||||
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
audiosample_get_buffer_structure(sample, /* single channel */ false,
|
||||
&self->single_buffer, &self->signed_to_unsigned, &max_buffer_length,
|
||||
&spacing);
|
||||
self->sample_channel_count = audiosample_channel_count(sample);
|
||||
self->sample_channel_count = audiosample_get_channel_count(sample);
|
||||
|
||||
mp_arg_validate_length_max(max_buffer_length, UINT16_MAX, MP_QSTR_buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ audio_dma_result audio_dma_setup_playback(
|
|||
dma->output_signed = output_signed;
|
||||
dma->sample_spacing = 1;
|
||||
dma->output_resolution = output_resolution;
|
||||
dma->sample_resolution = audiosample_bits_per_sample(sample);
|
||||
dma->sample_resolution = audiosample_get_bits_per_sample(sample);
|
||||
dma->output_register_address = output_register_address;
|
||||
dma->swap_channel = swap_channel;
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ audio_dma_result audio_dma_setup_playback(
|
|||
dma->output_size = 1;
|
||||
}
|
||||
// Transfer both channels at once.
|
||||
if (!single_channel_output && audiosample_channel_count(sample) == 2) {
|
||||
if (!single_channel_output && audiosample_get_channel_count(sample) == 2) {
|
||||
dma->output_size *= 2;
|
||||
}
|
||||
enum dma_channel_transfer_size dma_size = DMA_SIZE_8;
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
common_hal_audiobusio_i2sout_stop(self);
|
||||
}
|
||||
|
||||
uint8_t bits_per_sample = audiosample_bits_per_sample(sample);
|
||||
uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample);
|
||||
// Make sure we transmit a minimum of 16 bits.
|
||||
// TODO: Maybe we need an intermediate object to upsample instead. This is
|
||||
// only needed for some I2S devices that expect at least 8.
|
||||
|
|
@ -242,8 +242,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self,
|
|||
// We always output stereo so output twice as many bits.
|
||||
uint16_t bits_per_sample_output = bits_per_sample * 2;
|
||||
size_t clocks_per_bit = 6;
|
||||
uint32_t frequency = bits_per_sample_output * audiosample_sample_rate(sample);
|
||||
uint8_t channel_count = audiosample_channel_count(sample);
|
||||
uint32_t frequency = bits_per_sample_output * audiosample_get_sample_rate(sample);
|
||||
uint8_t channel_count = audiosample_get_channel_count(sample);
|
||||
if (channel_count > 2) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample."));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
|
|||
// to trigger the DMA. Each has a 16 bit fractional divisor system clock * X / Y where X and Y
|
||||
// are 16-bit.
|
||||
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
|
||||
uint32_t system_clock = common_hal_mcu_processor_get_frequency();
|
||||
uint32_t best_denominator;
|
||||
|
|
|
|||
|
|
@ -240,8 +240,8 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
|
|||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
||||
uint32_t sample_rate = audiosample_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
|
||||
uint32_t sample_rate = audiosample_get_sample_rate(sample);
|
||||
self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8;
|
||||
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
|
|
@ -249,7 +249,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self,
|
|||
bool samples_signed;
|
||||
audiosample_get_buffer_structure(sample, /* single channel */ false,
|
||||
&single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
self->sample_channel_count = audiosample_channel_count(sample);
|
||||
self->sample_channel_count = audiosample_get_channel_count(sample);
|
||||
self->sample_offset = (samples_signed ? 0x8000 : 0) - self->quiescent_value;
|
||||
|
||||
free_buffers(self);
|
||||
|
|
|
|||
|
|
@ -144,7 +144,6 @@ CFLAGS += \
|
|||
-DCIRCUITPY_AUDIOFILTERS=1 \
|
||||
-DCIRCUITPY_AUDIOMIXER=1 \
|
||||
-DCIRCUITPY_AUDIOMP3=1 \
|
||||
-DCIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR=0 \
|
||||
-DCIRCUITPY_AUDIOCORE_DEBUG=1 \
|
||||
-DCIRCUITPY_BITMAPTOOLS=1 \
|
||||
-DCIRCUITPY_CODEOP=1 \
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "shared-bindings/util.h"
|
||||
#include "shared-bindings/audiocore/RawSample.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
//| class RawSample:
|
||||
//| """A raw audio sample buffer in memory"""
|
||||
|
|
@ -120,12 +121,6 @@ static mp_obj_t audioio_rawsample_deinit(mp_obj_t self_in) {
|
|||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_deinit_obj, audioio_rawsample_deinit);
|
||||
|
||||
static void check_for_deinit(audioio_rawsample_obj_t *self) {
|
||||
if (common_hal_audioio_rawsample_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> RawSample:
|
||||
//| """No-op used by Context Managers."""
|
||||
//| ...
|
||||
|
|
@ -151,24 +146,6 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_rawsample___exit___obj, 4, 4,
|
|||
//| change it."""
|
||||
//|
|
||||
//|
|
||||
static mp_obj_t audioio_rawsample_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_rawsample_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_get_sample_rate_obj, audioio_rawsample_obj_get_sample_rate);
|
||||
|
||||
static mp_obj_t audioio_rawsample_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
|
||||
audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
common_hal_audioio_rawsample_set_sample_rate(self, mp_obj_get_int(sample_rate));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(audioio_rawsample_set_sample_rate_obj, audioio_rawsample_obj_set_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETSET(audioio_rawsample_sample_rate_obj,
|
||||
(mp_obj_t)&audioio_rawsample_get_sample_rate_obj,
|
||||
(mp_obj_t)&audioio_rawsample_set_sample_rate_obj);
|
||||
|
||||
static const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = {
|
||||
// Methods
|
||||
|
|
@ -177,18 +154,14 @@ static const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_rawsample___exit___obj) },
|
||||
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_rawsample_sample_rate_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audioio_rawsample_locals_dict, audioio_rawsample_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audioio_rawsample_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_rawsample_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_rawsample_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audioio_rawsample_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audioio_rawsample_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audioio_rawsample_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/audiocore/WaveFile.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-bindings/util.h"
|
||||
#include "extmod/vfs_posix.h"
|
||||
|
||||
|
|
@ -88,12 +89,6 @@ static mp_obj_t audioio_wavefile_deinit(mp_obj_t self_in) {
|
|||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_deinit_obj, audioio_wavefile_deinit);
|
||||
|
||||
static void check_for_deinit(audioio_wavefile_obj_t *self) {
|
||||
if (common_hal_audioio_wavefile_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> WaveFile:
|
||||
//| """No-op used by Context Managers."""
|
||||
//| ...
|
||||
|
|
@ -116,50 +111,14 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_wavefile___exit___obj, 4, 4,
|
|||
//| """32 bit value that dictates how quickly samples are loaded into the DAC
|
||||
//| in Hertz (cycles per second). When the sample is looped, this can change
|
||||
//| the pitch output without changing the underlying sample."""
|
||||
static mp_obj_t audioio_wavefile_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_sample_rate_obj, audioio_wavefile_obj_get_sample_rate);
|
||||
|
||||
static mp_obj_t audioio_wavefile_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
|
||||
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
common_hal_audioio_wavefile_set_sample_rate(self, mp_obj_get_int(sample_rate));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(audioio_wavefile_set_sample_rate_obj, audioio_wavefile_obj_set_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETSET(audioio_wavefile_sample_rate_obj,
|
||||
(mp_obj_t)&audioio_wavefile_get_sample_rate_obj,
|
||||
(mp_obj_t)&audioio_wavefile_set_sample_rate_obj);
|
||||
|
||||
//| bits_per_sample: int
|
||||
//| """Bits per sample. (read only)"""
|
||||
static mp_obj_t audioio_wavefile_obj_get_bits_per_sample(mp_obj_t self_in) {
|
||||
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_bits_per_sample(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_bits_per_sample_obj, audioio_wavefile_obj_get_bits_per_sample);
|
||||
|
||||
MP_PROPERTY_GETTER(audioio_wavefile_bits_per_sample_obj,
|
||||
(mp_obj_t)&audioio_wavefile_get_bits_per_sample_obj);
|
||||
//
|
||||
//| channel_count: int
|
||||
//| """Number of audio channels. (read only)"""
|
||||
//|
|
||||
//|
|
||||
static mp_obj_t audioio_wavefile_obj_get_channel_count(mp_obj_t self_in) {
|
||||
audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_channel_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_channel_count_obj, audioio_wavefile_obj_get_channel_count);
|
||||
|
||||
MP_PROPERTY_GETTER(audioio_wavefile_channel_count_obj,
|
||||
(mp_obj_t)&audioio_wavefile_get_channel_count_obj);
|
||||
|
||||
|
||||
static const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = {
|
||||
// Methods
|
||||
|
|
@ -168,20 +127,14 @@ static const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_wavefile___exit___obj) },
|
||||
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_wavefile_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audioio_wavefile_bits_per_sample_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audioio_wavefile_channel_count_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audioio_wavefile_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_wavefile_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_wavefile_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audioio_wavefile_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audioio_wavefile_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audioio_wavefile_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_wavefile_get_buffer_structure,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-bindings/audiocore/RawSample.h"
|
||||
#include "shared-bindings/audiocore/WaveFile.h"
|
||||
#include "shared-bindings/util.h"
|
||||
// #include "shared-bindings/audiomixer/Mixer.h"
|
||||
|
||||
//| """Support for audio samples"""
|
||||
|
|
@ -24,6 +26,9 @@ static mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) {
|
|||
uint32_t buffer_length = 0;
|
||||
audioio_get_buffer_result_t gbr = audiosample_get_buffer(sample_in, false, 0, &buffer, &buffer_length);
|
||||
|
||||
// audiosample_get_buffer checked that we're a sample so this is a safe cast
|
||||
audiosample_base_t *sample = MP_OBJ_TO_PTR(sample_in);
|
||||
|
||||
mp_obj_t result[2] = {mp_obj_new_int_from_uint(gbr), mp_const_none};
|
||||
|
||||
if (gbr != GET_BUFFER_ERROR) {
|
||||
|
|
@ -31,8 +36,8 @@ static mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) {
|
|||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
|
||||
uint8_t bits_per_sample = audiosample_bits_per_sample(sample_in);
|
||||
audiosample_get_buffer_structure(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample);
|
||||
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
// copies the data because the gc semantics of get_buffer are unclear
|
||||
void *result_buf = m_malloc(buffer_length);
|
||||
memcpy(result_buf, buffer, buffer_length);
|
||||
|
|
@ -55,7 +60,7 @@ static mp_obj_t audiocore_get_structure(mp_obj_t sample_in) {
|
|||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
|
||||
audiosample_get_buffer_structure(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
audiosample_get_buffer_structure_checked(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
mp_obj_t result[4] = {
|
||||
mp_obj_new_int_from_uint(single_buffer),
|
||||
mp_obj_new_int_from_uint(samples_signed),
|
||||
|
|
@ -92,4 +97,61 @@ const mp_obj_module_t audiocore_module = {
|
|||
.globals = (mp_obj_dict_t *)&audiocore_module_globals,
|
||||
};
|
||||
|
||||
bool audiosample_deinited(const audiosample_base_t *self) {
|
||||
return self->channel_count == 0;
|
||||
}
|
||||
|
||||
void audiosample_check_for_deinit(const audiosample_base_t *self) {
|
||||
if (audiosample_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
}
|
||||
|
||||
void audiosample_mark_deinit(audiosample_base_t *self) {
|
||||
self->channel_count = 0;
|
||||
}
|
||||
|
||||
// common implementation of channel_count property for audio samples
|
||||
static mp_obj_t audiosample_obj_get_channel_count(mp_obj_t self_in) {
|
||||
audiosample_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
audiosample_check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(audiosample_get_channel_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_channel_count_obj, audiosample_obj_get_channel_count);
|
||||
|
||||
MP_PROPERTY_GETTER(audiosample_channel_count_obj,
|
||||
(mp_obj_t)&audiosample_get_channel_count_obj);
|
||||
|
||||
|
||||
// common implementation of bits_per_sample property for audio samples
|
||||
static mp_obj_t audiosample_obj_get_bits_per_sample(mp_obj_t self_in) {
|
||||
audiosample_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
audiosample_check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(audiosample_get_bits_per_sample(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_bits_per_sample_obj, audiosample_obj_get_bits_per_sample);
|
||||
|
||||
MP_PROPERTY_GETTER(audiosample_bits_per_sample_obj,
|
||||
(mp_obj_t)&audiosample_get_bits_per_sample_obj);
|
||||
|
||||
// common implementation of sample_rate property for audio samples
|
||||
static mp_obj_t audiosample_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
audiosample_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
audiosample_check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(audiosample_get_sample_rate(audiosample_check(self_in)));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_sample_rate_obj, audiosample_obj_get_sample_rate);
|
||||
|
||||
static mp_obj_t audiosample_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
|
||||
audiosample_base_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
audiosample_check_for_deinit(self);
|
||||
audiosample_set_sample_rate(audiosample_check(self_in), mp_obj_get_int(sample_rate));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(audiosample_set_sample_rate_obj, audiosample_obj_set_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETSET(audiosample_sample_rate_obj,
|
||||
(mp_obj_t)&audiosample_get_sample_rate_obj,
|
||||
(mp_obj_t)&audiosample_set_sample_rate_obj);
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_audiocore, audiocore_module);
|
||||
|
|
|
|||
|
|
@ -5,3 +5,18 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "py/objproperty.h"
|
||||
|
||||
#define AUDIOSAMPLE_FIELDS \
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiosample_sample_rate_obj) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiosample_bits_per_sample_obj) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiosample_channel_count_obj) }
|
||||
|
||||
typedef struct audiosample_base audiosample_base_t;
|
||||
extern const mp_obj_property_getset_t audiosample_sample_rate_obj;
|
||||
extern const mp_obj_property_getter_t audiosample_bits_per_sample_obj;
|
||||
extern const mp_obj_property_getter_t audiosample_channel_count_obj;
|
||||
void audiosample_check_for_deinit(const audiosample_base_t *self);
|
||||
bool audiosample_deinited(const audiosample_base_t *self);
|
||||
void audiosample_mark_deinit(audiosample_base_t *self);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "shared-bindings/audiodelays/Echo.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-module/audiodelays/Echo.h"
|
||||
|
||||
#include "shared/runtime/context_manager_helpers.h"
|
||||
|
|
@ -122,9 +123,7 @@ static mp_obj_t audiodelays_echo_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_deinit_obj, audiodelays_echo_deinit);
|
||||
|
||||
static void check_for_deinit(audiodelays_echo_obj_t *self) {
|
||||
if (common_hal_audiodelays_echo_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> Echo:
|
||||
|
|
@ -292,17 +291,14 @@ static const mp_rom_map_elem_t audiodelays_echo_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_decay), MP_ROM_PTR(&audiodelays_echo_decay_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_echo_mix_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq_shift), MP_ROM_PTR(&audiodelays_echo_freq_shift_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiodelays_echo_locals_dict, audiodelays_echo_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audiodelays_echo_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audiodelays_echo_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiodelays_echo_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audiodelays_echo_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audiodelays_echo_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audiodelays_echo_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audiodelays_echo_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "shared-bindings/audiofilters/Distortion.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
#include "shared/runtime/context_manager_helpers.h"
|
||||
#include "py/binary.h"
|
||||
|
|
@ -161,9 +162,7 @@ static mp_obj_t audiofilters_distortion_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_deinit_obj, audiofilters_distortion_deinit);
|
||||
|
||||
static void check_for_deinit(audiofilters_distortion_obj_t *self) {
|
||||
if (common_hal_audiofilters_distortion_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> Distortion:
|
||||
|
|
@ -370,17 +369,14 @@ static const mp_rom_map_elem_t audiofilters_distortion_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&audiofilters_distortion_mode_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_soft_clip), MP_ROM_PTR(&audiofilters_distortion_soft_clip_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofilters_distortion_mix_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiofilters_distortion_locals_dict, audiofilters_distortion_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audiofilters_distortion_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audiofilters_distortion_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiofilters_distortion_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audiofilters_distortion_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audiofilters_distortion_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audiofilters_distortion_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audiofilters_distortion_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "shared-bindings/audiofilters/Filter.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-module/audiofilters/Filter.h"
|
||||
|
||||
#include "shared/runtime/context_manager_helpers.h"
|
||||
|
|
@ -109,9 +110,7 @@ static mp_obj_t audiofilters_filter_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_deinit_obj, audiofilters_filter_deinit);
|
||||
|
||||
static void check_for_deinit(audiofilters_filter_obj_t *self) {
|
||||
if (common_hal_audiofilters_filter_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> Filter:
|
||||
|
|
@ -238,17 +237,14 @@ static const mp_rom_map_elem_t audiofilters_filter_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofilters_filter_playing_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_filter), MP_ROM_PTR(&audiofilters_filter_filter_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofilters_filter_mix_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiofilters_filter_locals_dict, audiofilters_filter_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audiofilters_filter_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audiofilters_filter_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiofilters_filter_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audiofilters_filter_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audiofilters_filter_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audiofilters_filter_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audiofilters_filter_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
#include "shared-bindings/audiomixer/Mixer.h"
|
||||
#include "shared-bindings/audiomixer/MixerVoice.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-module/audiomixer/MixerVoice.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
|
@ -108,9 +109,7 @@ static mp_obj_t audiomixer_mixer_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_deinit_obj, audiomixer_mixer_deinit);
|
||||
|
||||
static void check_for_deinit(audiomixer_mixer_obj_t *self) {
|
||||
if (common_hal_audiomixer_mixer_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> Mixer:
|
||||
|
|
@ -145,15 +144,6 @@ MP_PROPERTY_GETTER(audiomixer_mixer_playing_obj,
|
|||
|
||||
//| sample_rate: int
|
||||
//| """32 bit value that dictates how quickly samples are played in Hertz (cycles per second)."""
|
||||
static mp_obj_t audiomixer_mixer_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomixer_mixer_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_get_sample_rate_obj, audiomixer_mixer_obj_get_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETTER(audiomixer_mixer_sample_rate_obj,
|
||||
(mp_obj_t)&audiomixer_mixer_get_sample_rate_obj);
|
||||
|
||||
//| voice: Tuple[MixerVoice, ...]
|
||||
//| """A tuple of the mixer's `audiomixer.MixerVoice` object(s).
|
||||
|
|
@ -244,19 +234,15 @@ static const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = {
|
|||
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixer_playing_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomixer_mixer_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_voice), MP_ROM_PTR(&audiomixer_mixer_voice_obj) }
|
||||
{ MP_ROM_QSTR(MP_QSTR_voice), MP_ROM_PTR(&audiomixer_mixer_voice_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audiomixer_mixer_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audiomixer_mixer_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomixer_mixer_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audiomixer_mixer_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audiomixer_mixer_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audiomixer_mixer_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "shared/runtime/context_manager_helpers.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
|
@ -122,9 +123,7 @@ static mp_obj_t audiomp3_mp3file_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_deinit_obj, audiomp3_mp3file_deinit);
|
||||
|
||||
static void check_for_deinit(audiomp3_mp3file_obj_t *self) {
|
||||
if (common_hal_audiomp3_mp3file_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> MP3Decoder:
|
||||
|
|
@ -193,48 +192,12 @@ MP_PROPERTY_GETSET(audiomp3_mp3file_file_obj,
|
|||
//| """32 bit value that dictates how quickly samples are loaded into the DAC
|
||||
//| in Hertz (cycles per second). When the sample is looped, this can change
|
||||
//| the pitch output without changing the underlying sample."""
|
||||
static mp_obj_t audiomp3_mp3file_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_sample_rate_obj, audiomp3_mp3file_obj_get_sample_rate);
|
||||
|
||||
static mp_obj_t audiomp3_mp3file_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) {
|
||||
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
common_hal_audiomp3_mp3file_set_sample_rate(self, mp_obj_get_int(sample_rate));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_sample_rate_obj, audiomp3_mp3file_obj_set_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETSET(audiomp3_mp3file_sample_rate_obj,
|
||||
(mp_obj_t)&audiomp3_mp3file_get_sample_rate_obj,
|
||||
(mp_obj_t)&audiomp3_mp3file_set_sample_rate_obj);
|
||||
|
||||
//| bits_per_sample: int
|
||||
//| """Bits per sample. (read only)"""
|
||||
static mp_obj_t audiomp3_mp3file_obj_get_bits_per_sample(mp_obj_t self_in) {
|
||||
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_bits_per_sample(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_bits_per_sample_obj, audiomp3_mp3file_obj_get_bits_per_sample);
|
||||
|
||||
MP_PROPERTY_GETTER(audiomp3_mp3file_bits_per_sample_obj,
|
||||
(mp_obj_t)&audiomp3_mp3file_get_bits_per_sample_obj);
|
||||
|
||||
//| channel_count: int
|
||||
//| """Number of audio channels. (read only)"""
|
||||
static mp_obj_t audiomp3_mp3file_obj_get_channel_count(mp_obj_t self_in) {
|
||||
audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_channel_count(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_channel_count_obj, audiomp3_mp3file_obj_get_channel_count);
|
||||
|
||||
MP_PROPERTY_GETTER(audiomp3_mp3file_channel_count_obj,
|
||||
(mp_obj_t)&audiomp3_mp3file_get_channel_count_obj);
|
||||
|
||||
//| rms_level: float
|
||||
//| """The RMS audio level of a recently played moment of audio. (read only)"""
|
||||
|
|
@ -272,22 +235,16 @@ static const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = {
|
|||
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_file), MP_ROM_PTR(&audiomp3_mp3file_file_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomp3_mp3file_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiomp3_mp3file_bits_per_sample_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiomp3_mp3file_channel_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_samples_decoded), MP_ROM_PTR(&audiomp3_mp3file_samples_decoded_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t audiomp3_mp3file_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_audiomp3_mp3file_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomp3_mp3file_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_audiomp3_mp3file_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)audiomp3_mp3file_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)audiomp3_mp3file_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomp3_mp3file_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self,
|
|||
|
||||
void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t stream);
|
||||
void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self);
|
||||
bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self);
|
||||
uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self);
|
||||
void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, uint32_t sample_rate);
|
||||
uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "shared-bindings/util.h"
|
||||
#include "shared-bindings/synthio/MidiTrack.h"
|
||||
#include "shared-bindings/synthio/__init__.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
//| class MidiTrack:
|
||||
//| """Simple MIDI synth"""
|
||||
|
|
@ -94,9 +95,7 @@ static mp_obj_t synthio_miditrack_deinit(mp_obj_t self_in) {
|
|||
static MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_deinit_obj, synthio_miditrack_deinit);
|
||||
|
||||
static void check_for_deinit(synthio_miditrack_obj_t *self) {
|
||||
if (common_hal_synthio_miditrack_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->synth.base);
|
||||
}
|
||||
|
||||
//| def __enter__(self) -> MidiTrack:
|
||||
|
|
@ -120,15 +119,6 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(synthio_miditrack___exit___obj, 4, 4,
|
|||
//| sample_rate: int
|
||||
//| """32 bit value that tells how quickly samples are played in Hertz (cycles per second)."""
|
||||
//|
|
||||
static mp_obj_t synthio_miditrack_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_synthio_miditrack_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_sample_rate_obj, synthio_miditrack_obj_get_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETTER(synthio_miditrack_sample_rate_obj,
|
||||
(mp_obj_t)&synthio_miditrack_get_sample_rate_obj);
|
||||
|
||||
//| error_location: Optional[int]
|
||||
//| """Offset, in bytes within the midi data, of a decoding error"""
|
||||
|
|
@ -155,19 +145,15 @@ static const mp_rom_map_elem_t synthio_miditrack_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&synthio_miditrack___exit___obj) },
|
||||
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_miditrack_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_error_location), MP_ROM_PTR(&synthio_miditrack_error_location_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(synthio_miditrack_locals_dict, synthio_miditrack_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t synthio_miditrack_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_synthio_miditrack_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_synthio_miditrack_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_synthio_miditrack_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)synthio_miditrack_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)synthio_miditrack_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_miditrack_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ extern const mp_obj_type_t synthio_miditrack_type;
|
|||
void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self, const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj);
|
||||
|
||||
void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self);
|
||||
bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self);
|
||||
uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self);
|
||||
uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self);
|
||||
uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include "shared-bindings/synthio/Synthesizer.h"
|
||||
#include "shared-bindings/synthio/LFO.h"
|
||||
#include "shared-bindings/synthio/__init__.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
//| NoteSequence = Sequence[Union[int, Note]]
|
||||
//| """A sequence of notes, which can each be integer MIDI note numbers or `Note` objects"""
|
||||
|
|
@ -72,9 +73,7 @@ static mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n
|
|||
}
|
||||
|
||||
static void check_for_deinit(synthio_synthesizer_obj_t *self) {
|
||||
if (common_hal_synthio_synthesizer_deinited(self)) {
|
||||
raise_deinited_error();
|
||||
}
|
||||
audiosample_check_for_deinit(&self->synth.base);
|
||||
}
|
||||
|
||||
//| def press(self, /, press: NoteOrNoteSequence = ()) -> None:
|
||||
|
|
@ -234,15 +233,6 @@ MP_PROPERTY_GETSET(synthio_synthesizer_envelope_obj,
|
|||
|
||||
//| sample_rate: int
|
||||
//| """32 bit value that tells how quickly samples are played in Hertz (cycles per second)."""
|
||||
static mp_obj_t synthio_synthesizer_obj_get_sample_rate(mp_obj_t self_in) {
|
||||
synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
check_for_deinit(self);
|
||||
return MP_OBJ_NEW_SMALL_INT(common_hal_synthio_synthesizer_get_sample_rate(self));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_get_sample_rate_obj, synthio_synthesizer_obj_get_sample_rate);
|
||||
|
||||
MP_PROPERTY_GETTER(synthio_synthesizer_sample_rate_obj,
|
||||
(mp_obj_t)&synthio_synthesizer_get_sample_rate_obj);
|
||||
|
||||
//| pressed: NoteSequence
|
||||
//| """A sequence of the currently pressed notes (read-only property).
|
||||
|
|
@ -332,7 +322,7 @@ static mp_obj_t synthio_synthesizer_lpf(size_t n_pos, const mp_obj_t *pos_args,
|
|||
args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) :
|
||||
mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q);
|
||||
|
||||
mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI;
|
||||
mp_float_t w0 = f0 / self->synth.base.sample_rate * 2 * MP_PI;
|
||||
|
||||
return common_hal_synthio_new_lpf(w0, Q);
|
||||
|
||||
|
|
@ -363,7 +353,7 @@ static mp_obj_t synthio_synthesizer_hpf(size_t n_pos, const mp_obj_t *pos_args,
|
|||
args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) :
|
||||
mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q);
|
||||
|
||||
mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI;
|
||||
mp_float_t w0 = f0 / self->synth.base.sample_rate * 2 * MP_PI;
|
||||
|
||||
return common_hal_synthio_new_hpf(w0, Q);
|
||||
|
||||
|
|
@ -397,7 +387,7 @@ static mp_obj_t synthio_synthesizer_bpf(size_t n_pos, const mp_obj_t *pos_args,
|
|||
args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) :
|
||||
mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q);
|
||||
|
||||
mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI;
|
||||
mp_float_t w0 = f0 / self->synth.base.sample_rate * 2 * MP_PI;
|
||||
|
||||
return common_hal_synthio_new_bpf(w0, Q);
|
||||
|
||||
|
|
@ -422,22 +412,18 @@ static const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_band_pass_filter), MP_ROM_PTR(&synthio_synthesizer_bpf_fun_obj) },
|
||||
// Properties
|
||||
{ MP_ROM_QSTR(MP_QSTR_envelope), MP_ROM_PTR(&synthio_synthesizer_envelope_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_synthesizer_sample_rate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_max_polyphony), MP_ROM_INT(CIRCUITPY_SYNTHIO_MAX_CHANNELS) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&synthio_synthesizer_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_note_info), MP_ROM_PTR(&synthio_synthesizer_note_info_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blocks), MP_ROM_PTR(&synthio_synthesizer_blocks_obj) },
|
||||
AUDIOSAMPLE_FIELDS,
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(synthio_synthesizer_locals_dict, synthio_synthesizer_locals_dict_table);
|
||||
|
||||
static const audiosample_p_t synthio_synthesizer_proto = {
|
||||
MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample)
|
||||
.sample_rate = (audiosample_sample_rate_fun)common_hal_synthio_synthesizer_get_sample_rate,
|
||||
.bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_synthio_synthesizer_get_bits_per_sample,
|
||||
.channel_count = (audiosample_channel_count_fun)common_hal_synthio_synthesizer_get_channel_count,
|
||||
.reset_buffer = (audiosample_reset_buffer_fun)synthio_synthesizer_reset_buffer,
|
||||
.get_buffer = (audiosample_get_buffer_fun)synthio_synthesizer_get_buffer,
|
||||
.get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_synthesizer_get_buffer_structure,
|
||||
};
|
||||
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self,
|
|||
uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj,
|
||||
mp_obj_t envelope_obj);
|
||||
void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self);
|
||||
bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self);
|
||||
uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self);
|
||||
uint8_t common_hal_synthio_synthesizer_get_bits_per_sample(synthio_synthesizer_obj_t *self);
|
||||
uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj_t *self);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "shared-bindings/audiocore/RawSample.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
@ -22,34 +23,18 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self,
|
|||
bool single_buffer) {
|
||||
|
||||
self->buffer = buffer;
|
||||
self->bits_per_sample = bytes_per_sample * 8;
|
||||
self->samples_signed = samples_signed;
|
||||
self->len = len;
|
||||
self->channel_count = channel_count;
|
||||
self->sample_rate = sample_rate;
|
||||
self->single_buffer = single_buffer;
|
||||
self->base.bits_per_sample = bytes_per_sample * 8;
|
||||
self->base.samples_signed = samples_signed;
|
||||
self->base.max_buffer_length = len;
|
||||
self->base.channel_count = channel_count;
|
||||
self->base.sample_rate = sample_rate;
|
||||
self->base.single_buffer = single_buffer;
|
||||
self->buffer_index = 0;
|
||||
}
|
||||
|
||||
void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self) {
|
||||
self->buffer = NULL;
|
||||
}
|
||||
bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self) {
|
||||
return self->buffer == NULL;
|
||||
}
|
||||
|
||||
uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t *self,
|
||||
uint32_t sample_rate) {
|
||||
self->sample_rate = sample_rate;
|
||||
}
|
||||
uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t *self) {
|
||||
return self->channel_count;
|
||||
audiosample_mark_deinit(&self->base);
|
||||
}
|
||||
|
||||
void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self,
|
||||
|
|
@ -63,37 +48,23 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t
|
|||
uint8_t **buffer,
|
||||
uint32_t *buffer_length) {
|
||||
|
||||
if (self->single_buffer) {
|
||||
*buffer_length = self->len;
|
||||
if (self->base.single_buffer) {
|
||||
*buffer_length = self->base.max_buffer_length;
|
||||
if (single_channel_output) {
|
||||
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8);
|
||||
*buffer = self->buffer + (channel % self->base.channel_count) * (self->base.bits_per_sample / 8);
|
||||
} else {
|
||||
*buffer = self->buffer;
|
||||
}
|
||||
return GET_BUFFER_DONE;
|
||||
} else {
|
||||
*buffer_length = self->len / 2;
|
||||
*buffer_length = self->base.max_buffer_length / 2;
|
||||
if (single_channel_output) {
|
||||
*buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8) + \
|
||||
self->len / 2 * self->buffer_index;
|
||||
*buffer = self->buffer + (channel % self->base.channel_count) * (self->base.bits_per_sample / 8) + \
|
||||
self->base.max_buffer_length / 2 * self->buffer_index;
|
||||
} else {
|
||||
*buffer = self->buffer + self->len / 2 * self->buffer_index;
|
||||
*buffer = self->buffer + self->base.max_buffer_length / 2 * self->buffer_index;
|
||||
}
|
||||
self->buffer_index = 1 - self->buffer_index;
|
||||
return GET_BUFFER_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
|
||||
*single_buffer = self->single_buffer;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->len;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,14 +11,8 @@
|
|||
#include "shared-module/audiocore/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
uint8_t bits_per_sample;
|
||||
bool samples_signed;
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
bool single_buffer;
|
||||
uint8_t buffer_index;
|
||||
} audioio_rawsample_obj_t;
|
||||
|
||||
|
|
@ -32,6 +26,3 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "py/runtime.h"
|
||||
|
||||
#include "shared-module/audiocore/WaveFile.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
struct wave_format_chunk {
|
||||
uint16_t audio_format;
|
||||
|
|
@ -71,9 +72,12 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self,
|
|||
mp_raise_ValueError(MP_ERROR_TEXT("Unsupported format"));
|
||||
}
|
||||
// Get the sample_rate
|
||||
self->sample_rate = format.sample_rate;
|
||||
self->channel_count = format.num_channels;
|
||||
self->bits_per_sample = format.bits_per_sample;
|
||||
self->base.sample_rate = format.sample_rate;
|
||||
self->base.channel_count = format.num_channels;
|
||||
self->base.bits_per_sample = format.bits_per_sample;
|
||||
self->base.samples_signed = format.bits_per_sample > 8;
|
||||
self->base.max_buffer_length = 512;
|
||||
self->base.single_buffer = false;
|
||||
|
||||
uint8_t chunk_tag[4];
|
||||
uint32_t chunk_length;
|
||||
|
|
@ -132,27 +136,7 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self,
|
|||
void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t *self) {
|
||||
self->buffer = NULL;
|
||||
self->second_buffer = NULL;
|
||||
}
|
||||
|
||||
bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t *self) {
|
||||
return self->buffer == NULL;
|
||||
}
|
||||
|
||||
uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t *self,
|
||||
uint32_t sample_rate) {
|
||||
self->sample_rate = sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t *self) {
|
||||
return self->channel_count;
|
||||
audiosample_mark_deinit(&self->base);
|
||||
}
|
||||
|
||||
void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self,
|
||||
|
|
@ -211,11 +195,11 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *
|
|||
if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) {
|
||||
uint32_t pad = length_read % sizeof(uint32_t);
|
||||
length_read += pad;
|
||||
if (self->bits_per_sample == 8) {
|
||||
if (self->base.bits_per_sample == 8) {
|
||||
for (uint32_t i = 0; i < pad; i++) {
|
||||
((uint8_t *)(*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80;
|
||||
}
|
||||
} else if (self->bits_per_sample == 16) {
|
||||
} else if (self->base.bits_per_sample == 16) {
|
||||
// We know the buffer is aligned because we allocated it onto the heap ourselves.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
|
@ -246,22 +230,8 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *
|
|||
self->left_read_count += 1;
|
||||
} else if (channel == 1) {
|
||||
self->right_read_count += 1;
|
||||
*buffer = *buffer + self->bits_per_sample / 8;
|
||||
*buffer = *buffer + self->base.bits_per_sample / 8;
|
||||
}
|
||||
|
||||
return self->bytes_remaining == 0 ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
*single_buffer = false;
|
||||
// In WAV files, 8-bit samples are always unsigned, and larger samples are always signed.
|
||||
*samples_signed = self->bits_per_sample > 8;
|
||||
*max_buffer_length = 512;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,16 @@
|
|||
#include "shared-module/audiocore/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
uint8_t *buffer;
|
||||
uint32_t buffer_length;
|
||||
uint8_t *second_buffer;
|
||||
uint32_t second_buffer_length;
|
||||
uint32_t file_length; // In bytes
|
||||
uint16_t data_start; // Where the data values start
|
||||
uint8_t bits_per_sample;
|
||||
uint16_t buffer_index;
|
||||
uint32_t bytes_remaining;
|
||||
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
|
||||
uint32_t len;
|
||||
pyb_file_obj_t *file;
|
||||
|
||||
|
|
@ -43,6 +39,3 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t *
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "shared-module/audioio/__init__.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/audiocore/RawSample.h"
|
||||
#include "shared-bindings/audiocore/WaveFile.h"
|
||||
#include "shared-module/audiocore/RawSample.h"
|
||||
|
|
@ -15,21 +16,6 @@
|
|||
#include "shared-bindings/audiomixer/Mixer.h"
|
||||
#include "shared-module/audiomixer/Mixer.h"
|
||||
|
||||
uint32_t audiosample_sample_rate(mp_obj_t sample_obj) {
|
||||
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
|
||||
return proto->sample_rate(MP_OBJ_TO_PTR(sample_obj));
|
||||
}
|
||||
|
||||
uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) {
|
||||
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
|
||||
return proto->bits_per_sample(MP_OBJ_TO_PTR(sample_obj));
|
||||
}
|
||||
|
||||
uint8_t audiosample_channel_count(mp_obj_t sample_obj) {
|
||||
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
|
||||
return proto->channel_count(MP_OBJ_TO_PTR(sample_obj));
|
||||
}
|
||||
|
||||
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel) {
|
||||
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
|
||||
proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, audio_channel);
|
||||
|
|
@ -43,14 +29,6 @@ audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
|
|||
return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, channel, buffer, buffer_length);
|
||||
}
|
||||
|
||||
void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj);
|
||||
proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel_output, single_buffer,
|
||||
samples_signed, max_buffer_length, spacing);
|
||||
}
|
||||
|
||||
void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes) {
|
||||
for (; nframes--;) {
|
||||
int16_t sample = (*buffer_in++ - 0x80) << 8;
|
||||
|
|
@ -217,3 +195,19 @@ void audiosample_convert_s16s_u8s(uint8_t *buffer_out, const int16_t *buffer_in,
|
|||
*buffer_out++ = sample;
|
||||
}
|
||||
}
|
||||
|
||||
void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in) {
|
||||
const audiosample_base_t *other = audiosample_check(other_in);
|
||||
if (other->sample_rate != self->sample_rate) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate);
|
||||
}
|
||||
if (other->channel_count != self->channel_count) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count);
|
||||
}
|
||||
if (other->bits_per_sample != self->bits_per_sample) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample);
|
||||
}
|
||||
if (other->samples_signed != self->samples_signed) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,40 +18,78 @@ typedef enum {
|
|||
GET_BUFFER_ERROR, // Error while reading data.
|
||||
} audioio_get_buffer_result_t;
|
||||
|
||||
typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t);
|
||||
typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t);
|
||||
typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t);
|
||||
typedef struct audiosample_base {
|
||||
mp_obj_base_t self;
|
||||
uint32_t sample_rate;
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t bits_per_sample;
|
||||
uint8_t channel_count;
|
||||
uint8_t samples_signed;
|
||||
bool single_buffer;
|
||||
} audiosample_base_t;
|
||||
|
||||
typedef void (*audiosample_reset_buffer_fun)(mp_obj_t,
|
||||
bool single_channel_output, uint8_t audio_channel);
|
||||
typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t,
|
||||
bool single_channel_output, uint8_t channel, uint8_t **buffer,
|
||||
uint32_t *buffer_length);
|
||||
typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t,
|
||||
bool single_channel_output, bool *single_buffer,
|
||||
bool *samples_signed, uint32_t *max_buffer_length,
|
||||
uint8_t *spacing);
|
||||
|
||||
typedef struct _audiosample_p_t {
|
||||
MP_PROTOCOL_HEAD // MP_QSTR_protocol_audiosample
|
||||
audiosample_sample_rate_fun sample_rate;
|
||||
audiosample_bits_per_sample_fun bits_per_sample;
|
||||
audiosample_channel_count_fun channel_count;
|
||||
audiosample_reset_buffer_fun reset_buffer;
|
||||
audiosample_get_buffer_fun get_buffer;
|
||||
audiosample_get_buffer_structure_fun get_buffer_structure;
|
||||
} audiosample_p_t;
|
||||
|
||||
uint32_t audiosample_sample_rate(mp_obj_t sample_obj);
|
||||
uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj);
|
||||
uint8_t audiosample_channel_count(mp_obj_t sample_obj);
|
||||
static inline uint32_t audiosample_get_bits_per_sample(audiosample_base_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
static inline uint32_t audiosample_get_sample_rate(audiosample_base_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
static inline void audiosample_set_sample_rate(audiosample_base_t *self, uint32_t sample_rate) {
|
||||
self->sample_rate = sample_rate;
|
||||
}
|
||||
|
||||
static inline uint8_t audiosample_get_channel_count(audiosample_base_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel);
|
||||
audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj,
|
||||
bool single_channel_output,
|
||||
uint8_t channel,
|
||||
uint8_t **buffer, uint32_t *buffer_length);
|
||||
void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output,
|
||||
|
||||
static inline void audiosample_get_buffer_structure(audiosample_base_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
|
||||
*single_buffer = self->single_buffer;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->max_buffer_length;
|
||||
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline audiosample_base_t *audiosample_check(mp_obj_t self_in) {
|
||||
// called for side effect
|
||||
(void)mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, self_in);
|
||||
return MP_OBJ_TO_PTR(self_in);
|
||||
}
|
||||
|
||||
static inline void audiosample_get_buffer_structure_checked(mp_obj_t self_in, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
audiosample_get_buffer_structure(audiosample_check(self_in), single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing);
|
||||
}
|
||||
|
||||
void audiosample_must_match(audiosample_base_t *self, mp_obj_t other);
|
||||
|
||||
void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes);
|
||||
void audiosample_convert_u8s_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes);
|
||||
|
|
|
|||
|
|
@ -19,10 +19,12 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
|
|||
|
||||
// Basic settings every effect and audio sample has
|
||||
// These are the effects values, not the source sample(s)
|
||||
self->bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.single_buffer = false;
|
||||
self->base.max_buffer_length = buffer_size;
|
||||
|
||||
// To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer
|
||||
// A double buffer is set up here so the audio output can use DMA on buffer 1 while we
|
||||
|
|
@ -78,7 +80,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
|
|||
|
||||
// Allocate the echo buffer for the max possible delay, echo is always 16-bit
|
||||
self->max_delay_ms = max_delay_ms;
|
||||
self->max_echo_buffer_len = (uint32_t)(self->sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms) * (self->channel_count * sizeof(uint16_t)); // bytes
|
||||
self->max_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms) * (self->base.channel_count * sizeof(uint16_t)); // bytes
|
||||
self->echo_buffer = m_malloc(self->max_echo_buffer_len);
|
||||
if (self->echo_buffer == NULL) {
|
||||
common_hal_audiodelays_echo_deinit(self);
|
||||
|
|
@ -87,7 +89,7 @@ void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_
|
|||
memset(self->echo_buffer, 0, self->max_echo_buffer_len);
|
||||
|
||||
// calculate the length of a single sample in milliseconds
|
||||
self->sample_ms = MICROPY_FLOAT_CONST(1000.0) / self->sample_rate;
|
||||
self->sample_ms = MICROPY_FLOAT_CONST(1000.0) / self->base.sample_rate;
|
||||
|
||||
// calculate everything needed for the current delay
|
||||
mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms);
|
||||
|
|
@ -140,7 +142,7 @@ void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) {
|
|||
self->echo_buffer_len = self->max_echo_buffer_len;
|
||||
} else {
|
||||
// Calculate the current echo buffer length in bytes
|
||||
uint32_t new_echo_buffer_len = (uint32_t)(self->sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * (self->channel_count * sizeof(uint16_t));
|
||||
uint32_t new_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * (self->base.channel_count * sizeof(uint16_t));
|
||||
|
||||
// Check if our new echo is too long for our maximum buffer
|
||||
if (new_echo_buffer_len > self->max_echo_buffer_len) {
|
||||
|
|
@ -189,18 +191,6 @@ void common_hal_audiodelays_echo_set_freq_shift(audiodelays_echo_obj_t *self, bo
|
|||
recalculate_delay(self, delay_ms);
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiodelays_echo_get_sample_rate(audiodelays_echo_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiodelays_echo_get_channel_count(audiodelays_echo_obj_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiodelays_echo_get_bits_per_sample(audiodelays_echo_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self,
|
||||
bool single_channel_output,
|
||||
uint8_t channel) {
|
||||
|
|
@ -215,27 +205,7 @@ bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self) {
|
|||
}
|
||||
|
||||
void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sample, bool loop) {
|
||||
// When a sample is to be played we must ensure the samples values matches what we expect
|
||||
// Then we reset the sample and get the first buffer to play
|
||||
// The get_buffer function will actually process that data
|
||||
|
||||
if (audiosample_sample_rate(sample) != self->sample_rate) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate);
|
||||
}
|
||||
if (audiosample_channel_count(sample) != self->channel_count) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count);
|
||||
}
|
||||
if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample);
|
||||
}
|
||||
bool single_buffer;
|
||||
bool samples_signed;
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
if (samples_signed != self->samples_signed) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
|
||||
}
|
||||
audiosample_must_match(&self->base, sample);
|
||||
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
|
@ -244,7 +214,7 @@ void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sam
|
|||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
|
||||
// Track remaining sample length in terms of bytes per sample
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
// Store if we have more data in the sample to retrieve
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
|
||||
|
|
@ -271,7 +241,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
// If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer
|
||||
int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx];
|
||||
int8_t *hword_buffer = self->buffer[self->last_buf_idx];
|
||||
uint32_t length = self->buffer_len / (self->bits_per_sample / 8);
|
||||
uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8);
|
||||
|
||||
// The echo buffer is always stored as a 16-bit value internally
|
||||
int16_t *echo_buffer = (int16_t *)self->echo_buffer;
|
||||
|
|
@ -291,7 +261,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
// Load another sample buffer to play
|
||||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
// Track length in terms of words.
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
}
|
||||
|
|
@ -299,13 +269,13 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
// Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining
|
||||
uint32_t n;
|
||||
if (self->sample == NULL) {
|
||||
n = MIN(length, SYNTHIO_MAX_DUR * self->channel_count);
|
||||
n = MIN(length, SYNTHIO_MAX_DUR * self->base.channel_count);
|
||||
} else {
|
||||
n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->channel_count);
|
||||
n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count);
|
||||
}
|
||||
|
||||
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, n / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
|
||||
mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
|
||||
mp_float_t decay = synthio_block_slot_get_limited(&self->decay, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
|
||||
|
||||
|
|
@ -328,17 +298,17 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
// If we have no sample keep the echo echoing
|
||||
if (self->sample == NULL) {
|
||||
if (mix <= MICROPY_FLOAT_CONST(0.01)) { // Mix of 0 is pure sample sound. We have no sample so no sound
|
||||
if (self->samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->bits_per_sample / 8));
|
||||
if (self->base.samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->base.bits_per_sample / 8));
|
||||
} else {
|
||||
// For unsigned samples set to the middle which is "quiet"
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
uint16_t *uword_buffer = (uint16_t *)word_buffer;
|
||||
while (length--) {
|
||||
*uword_buffer++ = 32768;
|
||||
}
|
||||
} else {
|
||||
memset(hword_buffer, 128, length * (self->bits_per_sample / 8));
|
||||
memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -363,14 +333,14 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
|
||||
word = (int16_t)(echo * mix);
|
||||
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = word;
|
||||
if (!self->samples_signed) {
|
||||
if (!self->base.samples_signed) {
|
||||
word_buffer[i] ^= 0x8000;
|
||||
}
|
||||
} else {
|
||||
hword_buffer[i] = (int8_t)word;
|
||||
if (!self->samples_signed) {
|
||||
if (!self->base.samples_signed) {
|
||||
hword_buffer[i] ^= 0x80;
|
||||
}
|
||||
}
|
||||
|
|
@ -396,7 +366,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
|
||||
if (mix <= MICROPY_FLOAT_CONST(0.01)) { // if mix is zero pure sample only
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = sample_src[i];
|
||||
} else {
|
||||
hword_buffer[i] = sample_hsrc[i];
|
||||
|
|
@ -405,10 +375,10 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
} else {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
int32_t sample_word = 0;
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
sample_word = sample_src[i];
|
||||
} else {
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
sample_word = sample_hsrc[i];
|
||||
} else {
|
||||
// Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed
|
||||
|
|
@ -426,7 +396,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
word = (int32_t)(echo * decay + sample_word);
|
||||
}
|
||||
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
if (self->freq_shift) {
|
||||
for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) {
|
||||
word = (int32_t)(echo_buffer[j % echo_buf_len] * decay + sample_word);
|
||||
|
|
@ -455,14 +425,14 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
word = echo + sample_word;
|
||||
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
|
||||
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix));
|
||||
if (!self->samples_signed) {
|
||||
if (!self->base.samples_signed) {
|
||||
word_buffer[i] ^= 0x8000;
|
||||
}
|
||||
} else {
|
||||
int8_t mixed = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix));
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
hword_buffer[i] = mixed;
|
||||
} else {
|
||||
hword_buffer[i] = (uint8_t)mixed ^ 0x80;
|
||||
|
|
@ -486,7 +456,7 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
length -= n;
|
||||
word_buffer += n;
|
||||
hword_buffer += n;
|
||||
self->sample_remaining_buffer += (n * (self->bits_per_sample / 8));
|
||||
self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8));
|
||||
self->sample_buffer_length -= n;
|
||||
}
|
||||
|
||||
|
|
@ -506,18 +476,3 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
// Echo always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h)
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
|
||||
// Return information about the effect's buffer (not the sample's)
|
||||
// These are used by calling audio objects to determine how to handle the effect's buffer
|
||||
*single_buffer = false;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->buffer_len;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
extern const mp_obj_type_t audiodelays_echo_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
uint32_t max_delay_ms;
|
||||
synthio_block_slot_t delay_ms;
|
||||
mp_float_t current_delay_ms;
|
||||
|
|
@ -22,11 +22,6 @@ typedef struct {
|
|||
synthio_block_slot_t decay;
|
||||
synthio_block_slot_t mix;
|
||||
|
||||
uint8_t bits_per_sample;
|
||||
bool samples_signed;
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
|
||||
int8_t *buffer[2];
|
||||
uint8_t last_buf_idx;
|
||||
uint32_t buffer_len; // max buffer in bytes
|
||||
|
|
@ -63,7 +58,3 @@ audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
|
||||
void audiodelays_echo_get_buffer_structure(audiodelays_echo_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -25,10 +25,12 @@ void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t
|
|||
|
||||
// Basic settings every effect and audio sample has
|
||||
// These are the effects values, not the source sample(s)
|
||||
self->bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.single_buffer = false;
|
||||
self->base.max_buffer_length = buffer_size;
|
||||
|
||||
// To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer
|
||||
// A double buffer is set up here so the audio output can use DMA on buffer 1 while we
|
||||
|
|
@ -131,18 +133,6 @@ void common_hal_audiofilters_distortion_set_mix(audiofilters_distortion_obj_t *s
|
|||
synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix);
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiofilters_distortion_get_sample_rate(audiofilters_distortion_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiofilters_distortion_get_channel_count(audiofilters_distortion_obj_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiofilters_distortion_get_bits_per_sample(audiofilters_distortion_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
void audiofilters_distortion_reset_buffer(audiofilters_distortion_obj_t *self,
|
||||
bool single_channel_output,
|
||||
uint8_t channel) {
|
||||
|
|
@ -156,27 +146,7 @@ bool common_hal_audiofilters_distortion_get_playing(audiofilters_distortion_obj_
|
|||
}
|
||||
|
||||
void common_hal_audiofilters_distortion_play(audiofilters_distortion_obj_t *self, mp_obj_t sample, bool loop) {
|
||||
// When a sample is to be played we must ensure the samples values matches what we expect
|
||||
// Then we reset the sample and get the first buffer to play
|
||||
// The get_buffer function will actually process that data
|
||||
|
||||
if (audiosample_sample_rate(sample) != self->sample_rate) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate);
|
||||
}
|
||||
if (audiosample_channel_count(sample) != self->channel_count) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count);
|
||||
}
|
||||
if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample);
|
||||
}
|
||||
bool single_buffer;
|
||||
bool samples_signed;
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
if (samples_signed != self->samples_signed) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
|
||||
}
|
||||
audiosample_must_match(&self->base, sample);
|
||||
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
|
@ -185,7 +155,7 @@ void common_hal_audiofilters_distortion_play(audiofilters_distortion_obj_t *self
|
|||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
|
||||
// Track remaining sample length in terms of bytes per sample
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
// Store if we have more data in the sample to retrieve
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
|
||||
|
|
@ -211,7 +181,7 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
// If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer
|
||||
int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx];
|
||||
int8_t *hword_buffer = self->buffer[self->last_buf_idx];
|
||||
uint32_t length = self->buffer_len / (self->bits_per_sample / 8);
|
||||
uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8);
|
||||
|
||||
// Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample
|
||||
while (length != 0) {
|
||||
|
|
@ -228,25 +198,25 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
// Load another sample buffer to play
|
||||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
// Track length in terms of words.
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->sample == NULL) {
|
||||
if (self->samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->bits_per_sample / 8));
|
||||
if (self->base.samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->base.bits_per_sample / 8));
|
||||
} else {
|
||||
// For unsigned samples set to the middle which is "quiet"
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
memset(word_buffer, 32768, length * (self->bits_per_sample / 8));
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
memset(word_buffer, 32768, length * (self->base.bits_per_sample / 8));
|
||||
} else {
|
||||
memset(hword_buffer, 128, length * (self->bits_per_sample / 8));
|
||||
memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8));
|
||||
}
|
||||
}
|
||||
|
||||
// tick all block inputs
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, length / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count);
|
||||
(void)synthio_block_slot_get(&self->drive);
|
||||
(void)synthio_block_slot_get(&self->pre_gain);
|
||||
(void)synthio_block_slot_get(&self->post_gain);
|
||||
|
|
@ -256,13 +226,13 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
} else {
|
||||
// we have a sample to play and apply effect
|
||||
// Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining
|
||||
uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->channel_count);
|
||||
uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count);
|
||||
|
||||
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples
|
||||
int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples
|
||||
|
||||
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, n / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
|
||||
mp_float_t drive = synthio_block_slot_get_limited(&self->drive, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
|
||||
mp_float_t pre_gain = db_to_linear(synthio_block_slot_get_limited(&self->pre_gain, MICROPY_FLOAT_CONST(-60.0), MICROPY_FLOAT_CONST(60.0)));
|
||||
mp_float_t post_gain = db_to_linear(synthio_block_slot_get_limited(&self->post_gain, MICROPY_FLOAT_CONST(-80.0), MICROPY_FLOAT_CONST(24.0)));
|
||||
|
|
@ -280,7 +250,7 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
|
||||
if (mix <= MICROPY_FLOAT_CONST(0.01)) { // if mix is zero pure sample only
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = sample_src[i];
|
||||
} else {
|
||||
hword_buffer[i] = sample_hsrc[i];
|
||||
|
|
@ -289,10 +259,10 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
} else {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
int32_t sample_word = 0;
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
sample_word = sample_src[i];
|
||||
} else {
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
sample_word = sample_hsrc[i];
|
||||
} else {
|
||||
// Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed
|
||||
|
|
@ -357,14 +327,14 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
word = MIN(MAX(word, -32767), 32768);
|
||||
}
|
||||
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix));
|
||||
if (!self->samples_signed) {
|
||||
if (!self->base.samples_signed) {
|
||||
word_buffer[i] ^= 0x8000;
|
||||
}
|
||||
} else {
|
||||
int8_t mixed = (int8_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix));
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
hword_buffer[i] = mixed;
|
||||
} else {
|
||||
hword_buffer[i] = (uint8_t)mixed ^ 0x80;
|
||||
|
|
@ -377,7 +347,7 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
length -= n;
|
||||
word_buffer += n;
|
||||
hword_buffer += n;
|
||||
self->sample_remaining_buffer += (n * (self->bits_per_sample / 8));
|
||||
self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8));
|
||||
self->sample_buffer_length -= n;
|
||||
}
|
||||
}
|
||||
|
|
@ -389,18 +359,3 @@ audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_dist
|
|||
// Distortion always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h)
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void audiofilters_distortion_get_buffer_structure(audiofilters_distortion_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
|
||||
// Return information about the effect's buffer (not the sample's)
|
||||
// These are used by calling audio objects to determine how to handle the effect's buffer
|
||||
*single_buffer = false;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->buffer_len;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ typedef enum {
|
|||
extern const mp_obj_type_t audiofilters_distortion_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
synthio_block_slot_t drive;
|
||||
synthio_block_slot_t pre_gain;
|
||||
synthio_block_slot_t post_gain;
|
||||
|
|
@ -29,11 +29,6 @@ typedef struct {
|
|||
bool soft_clip;
|
||||
synthio_block_slot_t mix;
|
||||
|
||||
uint8_t bits_per_sample;
|
||||
bool samples_signed;
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
|
||||
int8_t *buffer[2];
|
||||
uint8_t last_buf_idx;
|
||||
uint32_t buffer_len; // max buffer in bytes
|
||||
|
|
@ -54,7 +49,3 @@ void audiofilters_distortion_reset_buffer(audiofilters_distortion_obj_t *self,
|
|||
audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_distortion_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel,
|
||||
uint8_t **buffer, uint32_t *buffer_length);
|
||||
|
||||
void audiofilters_distortion_get_buffer_structure(audiofilters_distortion_obj_t *self,
|
||||
bool single_channel_output, bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self,
|
|||
|
||||
// Basic settings every effect and audio sample has
|
||||
// These are the effects values, not the source sample(s)
|
||||
self->bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places
|
||||
self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true)
|
||||
self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo
|
||||
self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects
|
||||
self->base.single_buffer = false;
|
||||
self->base.max_buffer_length = buffer_size;
|
||||
|
||||
// To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer
|
||||
// A double buffer is set up here so the audio output can use DMA on buffer 1 while we
|
||||
|
|
@ -138,18 +140,6 @@ void common_hal_audiofilters_filter_set_mix(audiofilters_filter_obj_t *self, mp_
|
|||
synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix);
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiofilters_filter_get_sample_rate(audiofilters_filter_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiofilters_filter_get_channel_count(audiofilters_filter_obj_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiofilters_filter_get_bits_per_sample(audiofilters_filter_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self,
|
||||
bool single_channel_output,
|
||||
uint8_t channel) {
|
||||
|
|
@ -170,27 +160,7 @@ bool common_hal_audiofilters_filter_get_playing(audiofilters_filter_obj_t *self)
|
|||
}
|
||||
|
||||
void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj_t sample, bool loop) {
|
||||
// When a sample is to be played we must ensure the samples values matches what we expect
|
||||
// Then we reset the sample and get the first buffer to play
|
||||
// The get_buffer function will actually process that data
|
||||
|
||||
if (audiosample_sample_rate(sample) != self->sample_rate) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate);
|
||||
}
|
||||
if (audiosample_channel_count(sample) != self->channel_count) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count);
|
||||
}
|
||||
if (audiosample_bits_per_sample(sample) != self->bits_per_sample) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample);
|
||||
}
|
||||
bool single_buffer;
|
||||
bool samples_signed;
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing);
|
||||
if (samples_signed != self->samples_signed) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
|
||||
}
|
||||
audiosample_must_match(&self->base, sample);
|
||||
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
|
@ -199,7 +169,7 @@ void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj
|
|||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
|
||||
// Track remaining sample length in terms of bytes per sample
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
// Store if we have more data in the sample to retrieve
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
|
||||
|
|
@ -226,7 +196,7 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
// If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer
|
||||
int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx];
|
||||
int8_t *hword_buffer = self->buffer[self->last_buf_idx];
|
||||
uint32_t length = self->buffer_len / (self->bits_per_sample / 8);
|
||||
uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8);
|
||||
|
||||
// Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample
|
||||
while (length != 0) {
|
||||
|
|
@ -243,27 +213,27 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
// Load another sample buffer to play
|
||||
audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length);
|
||||
// Track length in terms of words.
|
||||
self->sample_buffer_length /= (self->bits_per_sample / 8);
|
||||
self->sample_buffer_length /= (self->base.bits_per_sample / 8);
|
||||
self->more_data = result == GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->sample == NULL) {
|
||||
// tick all block inputs
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, length / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count);
|
||||
(void)synthio_block_slot_get(&self->mix);
|
||||
|
||||
if (self->samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->bits_per_sample / 8));
|
||||
if (self->base.samples_signed) {
|
||||
memset(word_buffer, 0, length * (self->base.bits_per_sample / 8));
|
||||
} else {
|
||||
// For unsigned samples set to the middle which is "quiet"
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
uint16_t *uword_buffer = (uint16_t *)word_buffer;
|
||||
while (length--) {
|
||||
*uword_buffer++ = 32768;
|
||||
}
|
||||
} else {
|
||||
memset(hword_buffer, 128, length * (self->bits_per_sample / 8));
|
||||
memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,18 +241,18 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
} else {
|
||||
// we have a sample to play and filter
|
||||
// Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining
|
||||
uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->channel_count);
|
||||
uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count);
|
||||
|
||||
int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples
|
||||
int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples
|
||||
|
||||
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, n / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
|
||||
mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
|
||||
|
||||
if (mix <= MICROPY_FLOAT_CONST(0.01) || !self->filter_states) { // if mix is zero pure sample only or no biquad filter objects are provided
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i] = sample_src[i];
|
||||
} else {
|
||||
hword_buffer[i] = sample_hsrc[i];
|
||||
|
|
@ -295,10 +265,10 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
|
||||
// Fill filter buffer with samples
|
||||
for (uint32_t j = 0; j < n_samples; j++) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
self->filter_buffer[j] = sample_src[i + j];
|
||||
} else {
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
self->filter_buffer[j] = sample_hsrc[i + j];
|
||||
} else {
|
||||
// Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed
|
||||
|
|
@ -314,13 +284,13 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
|
||||
// Mix processed signal with original sample and transfer to output buffer
|
||||
for (uint32_t j = 0; j < n_samples; j++) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
word_buffer[i + j] = synthio_mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)), SYNTHIO_MIX_DOWN_SCALE(2));
|
||||
if (!self->samples_signed) {
|
||||
if (!self->base.samples_signed) {
|
||||
word_buffer[i + j] ^= 0x8000;
|
||||
}
|
||||
} else {
|
||||
if (self->samples_signed) {
|
||||
if (self->base.samples_signed) {
|
||||
hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix));
|
||||
} else {
|
||||
hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)) ^ 0x80;
|
||||
|
|
@ -336,7 +306,7 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
length -= n;
|
||||
word_buffer += n;
|
||||
hword_buffer += n;
|
||||
self->sample_remaining_buffer += (n * (self->bits_per_sample / 8));
|
||||
self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8));
|
||||
self->sample_buffer_length -= n;
|
||||
}
|
||||
}
|
||||
|
|
@ -348,18 +318,3 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
// Filter always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h)
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
|
||||
// Return information about the effect's buffer (not the sample's)
|
||||
// These are used by calling audio objects to determine how to handle the effect's buffer
|
||||
*single_buffer = false;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->buffer_len;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,18 +16,13 @@
|
|||
extern const mp_obj_type_t audiofilters_filter_type;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
mp_obj_t *filter;
|
||||
synthio_block_slot_t mix;
|
||||
|
||||
size_t filter_states_len;
|
||||
biquad_filter_state *filter_states;
|
||||
|
||||
uint8_t bits_per_sample;
|
||||
bool samples_signed;
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
|
||||
int8_t *buffer[2];
|
||||
uint8_t last_buf_idx;
|
||||
uint32_t buffer_len; // max buffer in bytes
|
||||
|
|
@ -54,7 +49,3 @@ audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_o
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
|
||||
void audiofilters_filter_get_buffer_structure(audiofilters_filter_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -37,11 +37,13 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self,
|
|||
m_malloc_fail(self->len);
|
||||
}
|
||||
|
||||
self->bits_per_sample = bits_per_sample;
|
||||
self->samples_signed = samples_signed;
|
||||
self->channel_count = channel_count;
|
||||
self->sample_rate = sample_rate;
|
||||
self->base.bits_per_sample = bits_per_sample;
|
||||
self->base.samples_signed = samples_signed;
|
||||
self->base.channel_count = channel_count;
|
||||
self->base.sample_rate = sample_rate;
|
||||
self->base.single_buffer = false;
|
||||
self->voice_count = voice_count;
|
||||
self->base.max_buffer_length = buffer_size;
|
||||
}
|
||||
|
||||
void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self) {
|
||||
|
|
@ -53,18 +55,6 @@ bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self) {
|
|||
return self->first_buffer == NULL;
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t *self) {
|
||||
return self->bits_per_sample;
|
||||
}
|
||||
|
||||
bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self) {
|
||||
for (uint8_t v = 0; v < self->voice_count; v++) {
|
||||
if (common_hal_audiomixer_mixervoice_get_playing(MP_OBJ_TO_PTR(self->voice[v]))) {
|
||||
|
|
@ -191,10 +181,10 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
|
|||
uint32_t *src = voice->remaining_buffer;
|
||||
|
||||
#if CIRCUITPY_SYNTHIO
|
||||
uint32_t n = MIN(MIN(voice->buffer_length, length), SYNTHIO_MAX_DUR * self->channel_count);
|
||||
uint32_t n = MIN(MIN(voice->buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count);
|
||||
|
||||
// Get the current level from the BlockInput. These may change at run time so you need to do bounds checking if required.
|
||||
shared_bindings_synthio_lfo_tick(self->sample_rate, n / self->channel_count);
|
||||
shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count);
|
||||
uint16_t level = (uint16_t)(synthio_block_slot_get_limited(&voice->level, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * (1 << 15));
|
||||
#else
|
||||
uint32_t n = MIN(voice->buffer_length, length);
|
||||
|
|
@ -203,8 +193,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
|
|||
|
||||
// First active voice gets copied over verbatim.
|
||||
if (!voices_active) {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->samples_signed)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.samples_signed)) {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
uint32_t v = src[i];
|
||||
word_buffer[i] = mult16signed(v, level);
|
||||
|
|
@ -221,7 +211,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
|
|||
uint16_t *hsrc = (uint16_t *)src;
|
||||
for (uint32_t i = 0; i < n * 2; i++) {
|
||||
uint32_t word = unpack8(hsrc[i]);
|
||||
if (MP_LIKELY(!self->samples_signed)) {
|
||||
if (MP_LIKELY(!self->base.samples_signed)) {
|
||||
word = tosigned16(word);
|
||||
}
|
||||
word = mult16signed(word, level);
|
||||
|
|
@ -229,8 +219,8 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (MP_LIKELY(self->bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->samples_signed)) {
|
||||
if (MP_LIKELY(self->base.bits_per_sample == 16)) {
|
||||
if (MP_LIKELY(self->base.samples_signed)) {
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
uint32_t word = src[i];
|
||||
word_buffer[i] = add16signed(mult16signed(word, level), word_buffer[i]);
|
||||
|
|
@ -247,7 +237,7 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self,
|
|||
uint16_t *hsrc = (uint16_t *)src;
|
||||
for (uint32_t i = 0; i < n * 2; i++) {
|
||||
uint32_t word = unpack8(hsrc[i]);
|
||||
if (MP_LIKELY(!self->samples_signed)) {
|
||||
if (MP_LIKELY(!self->base.samples_signed)) {
|
||||
word = tosigned16(word);
|
||||
}
|
||||
word = mult16signed(word, level);
|
||||
|
|
@ -312,8 +302,8 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *
|
|||
}
|
||||
}
|
||||
|
||||
if (!self->samples_signed) {
|
||||
if (self->bits_per_sample == 16) {
|
||||
if (!self->base.samples_signed) {
|
||||
if (self->base.bits_per_sample == 16) {
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
word_buffer[i] = tounsigned16(word_buffer[i]);
|
||||
}
|
||||
|
|
@ -336,20 +326,7 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *
|
|||
self->left_read_count += 1;
|
||||
} else if (channel == 1) {
|
||||
self->right_read_count += 1;
|
||||
*buffer = *buffer + self->bits_per_sample / 8;
|
||||
*buffer = *buffer + self->base.bits_per_sample / 8;
|
||||
}
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
*single_buffer = false;
|
||||
*samples_signed = self->samples_signed;
|
||||
*max_buffer_length = self->len;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,15 +12,11 @@
|
|||
#include "shared-module/audiocore/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
uint32_t *first_buffer;
|
||||
uint32_t *second_buffer;
|
||||
uint32_t len; // in words
|
||||
uint8_t bits_per_sample;
|
||||
bool use_first_buffer;
|
||||
bool samples_signed;
|
||||
uint8_t channel_count;
|
||||
uint32_t sample_rate;
|
||||
|
||||
uint32_t read_count;
|
||||
uint32_t left_read_count;
|
||||
|
|
@ -41,6 +37,3 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t *
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -46,25 +46,10 @@ void common_hal_audiomixer_mixervoice_set_loop(audiomixer_mixervoice_obj_t *self
|
|||
self->loop = loop;
|
||||
}
|
||||
|
||||
void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample, bool loop) {
|
||||
if (audiosample_sample_rate(sample) != self->parent->sample_rate) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate);
|
||||
}
|
||||
if (audiosample_channel_count(sample) != self->parent->channel_count) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count);
|
||||
}
|
||||
if (audiosample_bits_per_sample(sample) != self->parent->bits_per_sample) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample);
|
||||
}
|
||||
bool single_buffer;
|
||||
bool samples_signed;
|
||||
uint32_t max_buffer_length;
|
||||
uint8_t spacing;
|
||||
audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed,
|
||||
&max_buffer_length, &spacing);
|
||||
if (samples_signed != self->parent->samples_signed) {
|
||||
mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness);
|
||||
}
|
||||
void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample_in, bool loop) {
|
||||
audiosample_must_match(&self->parent->base, sample_in);
|
||||
// cast is safe, checked by must_match
|
||||
audiosample_base_t *sample = MP_OBJ_TO_PTR(sample_in);
|
||||
self->sample = sample;
|
||||
self->loop = loop;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "shared-bindings/audiomp3/MP3Decoder.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -168,7 +169,7 @@ static bool mp3file_update_inbuf_always(audiomp3_mp3file_obj_t *self, bool block
|
|||
*/
|
||||
static void mp3file_update_inbuf_cb(void *self_in) {
|
||||
audiomp3_mp3file_obj_t *self = self_in;
|
||||
if (common_hal_audiomp3_mp3file_deinited(self_in)) {
|
||||
if (audiosample_deinited(&self->base)) {
|
||||
return;
|
||||
}
|
||||
if (!self->eof && stream_readable(self->stream)) {
|
||||
|
|
@ -380,14 +381,18 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t
|
|||
MP_ERROR_TEXT("Failed to parse MP3 file"));
|
||||
}
|
||||
|
||||
self->sample_rate = fi.samprate;
|
||||
self->channel_count = fi.nChans;
|
||||
self->frame_buffer_size = fi.outputSamps * sizeof(int16_t);
|
||||
self->len = 2 * self->frame_buffer_size;
|
||||
self->base.sample_rate = fi.samprate;
|
||||
self->base.channel_count = fi.nChans;
|
||||
self->base.single_buffer = false;
|
||||
self->base.bits_per_sample = 16;
|
||||
self->base.samples_signed = false;
|
||||
self->base.max_buffer_length = fi.outputSamps * sizeof(int16_t);
|
||||
self->len = 2 * self->base.max_buffer_length;
|
||||
self->samples_decoded = 0;
|
||||
}
|
||||
|
||||
void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) {
|
||||
audiosample_mark_deinit(&self->base);
|
||||
if (self->decoder) {
|
||||
MP3FreeDecoder(self->decoder);
|
||||
}
|
||||
|
|
@ -400,27 +405,6 @@ void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) {
|
|||
self->samples_decoded = 0;
|
||||
}
|
||||
|
||||
bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self) {
|
||||
return self->pcm_buffer[0] == NULL;
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self) {
|
||||
return self->sample_rate;
|
||||
}
|
||||
|
||||
void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self,
|
||||
uint32_t sample_rate) {
|
||||
self->sample_rate = sample_rate;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self) {
|
||||
return 16;
|
||||
}
|
||||
|
||||
uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self) {
|
||||
return self->channel_count;
|
||||
}
|
||||
|
||||
void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self,
|
||||
bool single_channel_output,
|
||||
uint8_t channel) {
|
||||
|
|
@ -457,7 +441,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
channel = 0;
|
||||
}
|
||||
|
||||
size_t frame_buffer_size_bytes = self->frame_buffer_size;
|
||||
size_t frame_buffer_size_bytes = self->base.max_buffer_length;
|
||||
*buffer_length = frame_buffer_size_bytes;
|
||||
|
||||
if (channel == self->other_channel) {
|
||||
|
|
@ -479,7 +463,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
|
||||
mp3file_skip_id3v2(self, false);
|
||||
if (!mp3file_find_sync_word(self, false)) {
|
||||
memset(buffer, 0, self->frame_buffer_size);
|
||||
memset(buffer, 0, self->base.max_buffer_length);
|
||||
*buffer_length = 0;
|
||||
return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR;
|
||||
}
|
||||
|
|
@ -495,7 +479,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
mp_printf(&mp_plat_print, "%s:%d err=%d\n", __FILE__, __LINE__, err);
|
||||
}
|
||||
if (self->eof || (err != ERR_MP3_INDATA_UNDERFLOW && err != ERR_MP3_MAINDATA_UNDERFLOW)) {
|
||||
memset(buffer, 0, self->frame_buffer_size);
|
||||
memset(buffer, 0, self->base.max_buffer_length);
|
||||
*buffer_length = 0;
|
||||
self->eof = true;
|
||||
return GET_BUFFER_ERROR;
|
||||
|
|
@ -523,27 +507,14 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
return result;
|
||||
}
|
||||
|
||||
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
*single_buffer = false;
|
||||
*samples_signed = true;
|
||||
*max_buffer_length = self->frame_buffer_size;
|
||||
if (single_channel_output) {
|
||||
*spacing = self->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self) {
|
||||
float sumsq = 0.f;
|
||||
// Assumes no DC component to the audio. Is that a safe assumption?
|
||||
int16_t *buffer = (int16_t *)(void *)self->pcm_buffer[self->buffer_index];
|
||||
for (size_t i = 0; i < self->frame_buffer_size / sizeof(int16_t); i++) {
|
||||
for (size_t i = 0; i < self->base.max_buffer_length / sizeof(int16_t); i++) {
|
||||
sumsq += (float)buffer[i] * buffer[i];
|
||||
}
|
||||
return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t));
|
||||
return sqrtf(sumsq) / (self->base.max_buffer_length / sizeof(int16_t));
|
||||
}
|
||||
|
||||
uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self) {
|
||||
|
|
|
|||
|
|
@ -21,19 +21,16 @@ typedef struct {
|
|||
} mp3_input_buffer_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
audiosample_base_t base;
|
||||
struct _MP3DecInfo *decoder;
|
||||
background_callback_t inbuf_fill_cb;
|
||||
mp3_input_buffer_t inbuf;
|
||||
int16_t *pcm_buffer[2];
|
||||
uint32_t len;
|
||||
uint32_t frame_buffer_size;
|
||||
|
||||
uint32_t sample_rate;
|
||||
mp_obj_t stream;
|
||||
|
||||
uint8_t buffer_index;
|
||||
uint8_t channel_count;
|
||||
bool eof;
|
||||
bool block_ok;
|
||||
mp_obj_t settimeout_args[3];
|
||||
|
|
@ -53,9 +50,6 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t *
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
||||
float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/synthio/MidiTrack.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
|
||||
|
||||
static void record_midi_stream_error(synthio_miditrack_obj_t *self) {
|
||||
|
|
@ -42,7 +43,7 @@ static int decode_duration(synthio_miditrack_obj_t *self) {
|
|||
self->pos = self->track.len;
|
||||
record_midi_stream_error(self);
|
||||
}
|
||||
return delta * self->synth.sample_rate / self->tempo;
|
||||
return delta * self->synth.base.sample_rate / self->tempo;
|
||||
}
|
||||
|
||||
// invariant: pointing at a MIDI message
|
||||
|
|
@ -111,24 +112,10 @@ void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self) {
|
|||
synthio_synth_deinit(&self->synth);
|
||||
}
|
||||
|
||||
bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self) {
|
||||
return synthio_synth_deinited(&self->synth);
|
||||
}
|
||||
|
||||
mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self) {
|
||||
return self->error_location;
|
||||
}
|
||||
|
||||
uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self) {
|
||||
return self->synth.sample_rate;
|
||||
}
|
||||
uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self) {
|
||||
return SYNTHIO_BITS_PER_SAMPLE;
|
||||
}
|
||||
uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel) {
|
||||
synthio_synth_reset_buffer(&self->synth, single_channel_output, channel);
|
||||
|
|
@ -137,7 +124,7 @@ void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self,
|
|||
|
||||
audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) {
|
||||
if (common_hal_synthio_miditrack_deinited(self)) {
|
||||
if (audiosample_deinited(&self->synth.base)) {
|
||||
*buffer_length = 0;
|
||||
return GET_BUFFER_ERROR;
|
||||
}
|
||||
|
|
@ -152,8 +139,3 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
|
|||
}
|
||||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include "shared-module/synthio/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
synthio_synth_t synth;
|
||||
mp_buffer_info_t track;
|
||||
// invariant: after initial startup, pos always points just after an encoded duration, i.e., at a midi message (or at EOF)
|
||||
|
|
@ -31,7 +30,3 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
|
||||
void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "shared-bindings/synthio/LFO.h"
|
||||
#include "shared-bindings/synthio/Note.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-bindings/synthio/Synthesizer.h"
|
||||
#include "shared-module/synthio/Note.h"
|
||||
|
||||
|
|
@ -23,19 +24,6 @@ void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self,
|
|||
void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self) {
|
||||
synthio_synth_deinit(&self->synth);
|
||||
}
|
||||
bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self) {
|
||||
return synthio_synth_deinited(&self->synth);
|
||||
}
|
||||
|
||||
uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self) {
|
||||
return self->synth.sample_rate;
|
||||
}
|
||||
uint8_t common_hal_synthio_synthesizer_get_bits_per_sample(synthio_synthesizer_obj_t *self) {
|
||||
return SYNTHIO_BITS_PER_SAMPLE;
|
||||
}
|
||||
uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj_t *self) {
|
||||
return self->synth.channel_count;
|
||||
}
|
||||
|
||||
void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel) {
|
||||
|
|
@ -44,7 +32,7 @@ void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self,
|
|||
|
||||
audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_obj_t *self,
|
||||
bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) {
|
||||
if (common_hal_synthio_synthesizer_deinited(self)) {
|
||||
if (audiosample_deinited(&self->synth.base)) {
|
||||
*buffer_length = 0;
|
||||
return GET_BUFFER_ERROR;
|
||||
}
|
||||
|
|
@ -67,11 +55,6 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o
|
|||
return GET_BUFFER_MORE_DATA;
|
||||
}
|
||||
|
||||
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing);
|
||||
}
|
||||
|
||||
void common_hal_synthio_synthesizer_release_all(synthio_synthesizer_obj_t *self) {
|
||||
for (size_t i = 0; i < CIRCUITPY_SYNTHIO_MAX_CHANNELS; i++) {
|
||||
if (self->synth.span.note_obj[i] != SYNTHIO_SILENCE) {
|
||||
|
|
@ -114,7 +97,7 @@ void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_ob
|
|||
if (is_note(to_press)) {
|
||||
if (!mp_obj_is_small_int(to_press)) {
|
||||
synthio_note_obj_t *note = MP_OBJ_TO_PTR(to_press);
|
||||
synthio_note_start(note, self->synth.sample_rate);
|
||||
synthio_note_start(note, self->synth.base.sample_rate);
|
||||
}
|
||||
synthio_span_change_note(&self->synth, SYNTHIO_SILENCE, validate_note(to_press));
|
||||
return;
|
||||
|
|
@ -127,7 +110,7 @@ void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_ob
|
|||
note_obj = validate_note(note_obj);
|
||||
if (!mp_obj_is_small_int(note_obj)) {
|
||||
synthio_note_obj_t *note = MP_OBJ_TO_PTR(note_obj);
|
||||
synthio_note_start(note, self->synth.sample_rate);
|
||||
synthio_note_start(note, self->synth.base.sample_rate);
|
||||
}
|
||||
synthio_span_change_note(&self->synth, SYNTHIO_SILENCE, note_obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include "shared-module/synthio/__init__.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
synthio_synth_t synth;
|
||||
mp_obj_t blocks;
|
||||
} synthio_synthesizer_obj_t;
|
||||
|
|
@ -28,7 +27,3 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o
|
|||
uint8_t channel,
|
||||
uint8_t **buffer,
|
||||
uint32_t *buffer_length); // length in bytes
|
||||
|
||||
void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed,
|
||||
uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "shared-module/synthio/__init__.h"
|
||||
#include "shared-bindings/audiocore/__init__.h"
|
||||
#include "shared-bindings/synthio/__init__.h"
|
||||
#include "shared-module/synthio/Biquad.h"
|
||||
#include "shared-module/synthio/BlockBiquad.h"
|
||||
|
|
@ -154,7 +155,7 @@ int16_t synthio_mix_down_sample(int32_t sample, int32_t scale) {
|
|||
static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *out_buffer32, int16_t dur, int16_t loudness[2]) {
|
||||
mp_obj_t note_obj = synth->span.note_obj[chan];
|
||||
|
||||
int32_t sample_rate = synth->sample_rate;
|
||||
int32_t sample_rate = synth->base.sample_rate;
|
||||
|
||||
|
||||
uint32_t dds_rate;
|
||||
|
|
@ -290,7 +291,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
|
|||
return;
|
||||
}
|
||||
|
||||
shared_bindings_synthio_lfo_tick(synth->sample_rate, SYNTHIO_MAX_DUR);
|
||||
shared_bindings_synthio_lfo_tick(synth->base.sample_rate, SYNTHIO_MAX_DUR);
|
||||
|
||||
synth->buffer_index = !synth->buffer_index;
|
||||
synth->other_channel = 1 - channel;
|
||||
|
|
@ -299,9 +300,9 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
|
|||
uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur);
|
||||
synth->span.dur -= dur;
|
||||
|
||||
int32_t out_buffer32[SYNTHIO_MAX_DUR * synth->channel_count];
|
||||
int32_t out_buffer32[SYNTHIO_MAX_DUR * synth->base.channel_count];
|
||||
int32_t tmp_buffer32[SYNTHIO_MAX_DUR];
|
||||
memset(out_buffer32, 0, synth->channel_count * dur * sizeof(int32_t));
|
||||
memset(out_buffer32, 0, synth->base.channel_count * dur * sizeof(int32_t));
|
||||
|
||||
for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) {
|
||||
mp_obj_t note_obj = synth->span.note_obj[chan];
|
||||
|
|
@ -333,13 +334,13 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
|
|||
}
|
||||
|
||||
// adjust loudness by envelope
|
||||
sum_with_loudness(out_buffer32, tmp_buffer32, loudness, dur, synth->channel_count);
|
||||
sum_with_loudness(out_buffer32, tmp_buffer32, loudness, dur, synth->base.channel_count);
|
||||
}
|
||||
|
||||
int16_t *out_buffer16 = (int16_t *)(void *)synth->buffers[synth->buffer_index];
|
||||
|
||||
// mix down audio
|
||||
for (size_t i = 0; i < dur * synth->channel_count; i++) {
|
||||
for (size_t i = 0; i < dur * synth->base.channel_count; i++) {
|
||||
int32_t sample = out_buffer32[i];
|
||||
out_buffer16[i] = synthio_mix_down_sample(sample, SYNTHIO_MIX_DOWN_SCALE(CIRCUITPY_SYNTHIO_MAX_CHANNELS));
|
||||
}
|
||||
|
|
@ -353,7 +354,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t
|
|||
synthio_envelope_state_step(&synth->envelope_state[chan], synthio_synth_get_note_envelope(synth, note_obj), dur);
|
||||
}
|
||||
|
||||
*buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE * synth->channel_count;
|
||||
*buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE * synth->base.channel_count;
|
||||
*bufptr = (uint8_t *)out_buffer16;
|
||||
}
|
||||
|
||||
|
|
@ -364,17 +365,14 @@ void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_outp
|
|||
synth->other_channel = -1;
|
||||
}
|
||||
|
||||
bool synthio_synth_deinited(synthio_synth_t *synth) {
|
||||
return synth->buffers[0] == NULL;
|
||||
}
|
||||
|
||||
void synthio_synth_deinit(synthio_synth_t *synth) {
|
||||
synth->buffers[0] = NULL;
|
||||
synth->buffers[1] = NULL;
|
||||
audiosample_mark_deinit(&synth->base);
|
||||
}
|
||||
|
||||
void synthio_synth_envelope_set(synthio_synth_t *synth, mp_obj_t envelope_obj) {
|
||||
synthio_envelope_definition_set(&synth->global_envelope_definition, envelope_obj, synth->sample_rate);
|
||||
synthio_envelope_definition_set(&synth->global_envelope_definition, envelope_obj, synth->base.sample_rate);
|
||||
synth->envelope_obj = envelope_obj;
|
||||
}
|
||||
|
||||
|
|
@ -388,10 +386,14 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
|
|||
synth->buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count;
|
||||
synth->buffers[0] = m_malloc(synth->buffer_length);
|
||||
synth->buffers[1] = m_malloc(synth->buffer_length);
|
||||
synth->channel_count = channel_count;
|
||||
synth->base.channel_count = channel_count;
|
||||
synth->base.single_buffer = false;
|
||||
synth->other_channel = -1;
|
||||
synth->waveform_obj = waveform_obj;
|
||||
synth->sample_rate = sample_rate;
|
||||
synth->base.sample_rate = sample_rate;
|
||||
synth->base.bits_per_sample = 16;
|
||||
synth->base.samples_signed = true;
|
||||
synth->base.max_buffer_length = synth->buffer_length;
|
||||
synthio_synth_envelope_set(synth, envelope_obj);
|
||||
|
||||
for (size_t i = 0; i < CIRCUITPY_SYNTHIO_MAX_CHANNELS; i++) {
|
||||
|
|
@ -399,18 +401,6 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe
|
|||
}
|
||||
}
|
||||
|
||||
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) {
|
||||
*single_buffer = false;
|
||||
*samples_signed = true;
|
||||
*max_buffer_length = synth->buffer_length;
|
||||
if (single_channel_output) {
|
||||
*spacing = synth->channel_count;
|
||||
} else {
|
||||
*spacing = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp_int_t max_len) {
|
||||
if (o != mp_const_none) {
|
||||
mp_get_buffer_raise(o, bufinfo, MP_BUFFER_READ);
|
||||
|
|
|
|||
|
|
@ -41,10 +41,9 @@ typedef struct {
|
|||
} synthio_envelope_state_t;
|
||||
|
||||
typedef struct synthio_synth {
|
||||
uint32_t sample_rate;
|
||||
audiosample_base_t base;
|
||||
uint32_t total_envelope;
|
||||
int16_t *buffers[2];
|
||||
uint8_t channel_count;
|
||||
uint16_t buffer_length;
|
||||
uint16_t last_buffer_length;
|
||||
uint8_t other_channel, buffer_index, other_buffer_index;
|
||||
|
|
@ -71,8 +70,6 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t
|
|||
void synthio_synth_deinit(synthio_synth_t *synth);
|
||||
bool synthio_synth_deinited(synthio_synth_t *synth);
|
||||
void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t envelope);
|
||||
void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output,
|
||||
bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing);
|
||||
void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel);
|
||||
void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj);
|
||||
void synthio_synth_parse_filter(mp_buffer_info_t *bufinfo_filter, mp_obj_t filter_obj);
|
||||
|
|
|
|||
Loading…
Reference in a new issue