1717//| """A raw audio sample buffer in memory"""
1818//|
1919//| def __init__(
20- //| self, buffer: ReadableBuffer, *, channel_count: int = 1, sample_rate: int = 8000
20+ //| self,
21+ //| buffer: ReadableBuffer,
22+ //| *,
23+ //| channel_count: int = 1,
24+ //| sample_rate: int = 8000,
25+ //| single_buffer: bool = True
2126//| ) -> None:
2227//| """Create a RawSample based on the given buffer of values. If channel_count is more than
2328//| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the
2732//| :param ~circuitpython_typing.ReadableBuffer buffer: A buffer with samples
2833//| :param int channel_count: The number of channels in the buffer
2934//| :param int sample_rate: The desired playback sample rate
35+ //| :param bool single_buffer: Selects single buffered or double buffered transfer mode. This affects sample looping
36+ //| and what happens if the sample buffer is changed while the sample is playing.
37+ //| In single buffered transfers, samples will play once unless the play method is invoked with
38+ //| loop=True. A change in buffer contents will not affect active playback.
39+ //| In double buffered transfers, samples are always looped, and changed buffer contents will
40+ //| be played back as soon as transfer reaches the next half-buffer point.
3041//|
31- //| Simple 8ksps 440 Hz sin wave ::
42+ //| Playing 8ksps 440 Hz and 880 Hz sine waves ::
3243//|
44+ //| import analogbufio
45+ //| import array
3346//| import audiocore
34- //| import audioio
47+ //| import audiopwmio
3548//| import board
36- //| import array
37- //| import time
3849//| import math
50+ //| import time
3951//|
40- //| # Generate one period of sine wav .
52+ //| # Generate one period of sine wave .
4153//| length = 8000 // 440
4254//| sine_wave = array.array("h", [0] * length)
4355//| for i in range(length):
4456//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
57+ //| pwm = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
4558//|
46- //| dac = audioio.AudioOut(board.SPEAKER)
47- //| sine_wave = audiocore.RawSample(sine_wave)
48- //| dac.play(sine_wave, loop=True)
59+ //| # Play single-buffered
60+ //| sample = audiocore.RawSample(sine_wave)
61+ //| pwm.play(sample, loop=True)
62+ //| time.sleep(3)
63+ //| # changing the wave has no effect
64+ //| for i in range(length):
65+ //| sine_wave[i] = int(math.sin(math.pi * 4 * i / length) * (2 ** 15))
66+ //| time.sleep(3)
67+ //| pwm.stop()
4968//| time.sleep(1)
50- //| dac.stop()"""
69+ //|
70+ //| # Play double-buffered
71+ //| sample = audiocore.RawSample(sine_wave, single_buffer=False)
72+ //| pwm.play(sample)
73+ //| time.sleep(3)
74+ //| # changing the wave takes effect almost immediately
75+ //| for i in range(length):
76+ //| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
77+ //| time.sleep(3)
78+ //| pwm.stop()
79+ //| pwm.deinit()"""
5180//| ...
5281static mp_obj_t audioio_rawsample_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
53- enum { ARG_buffer , ARG_channel_count , ARG_sample_rate };
82+ enum { ARG_buffer , ARG_channel_count , ARG_sample_rate , ARG_single_buffer };
5483 static const mp_arg_t allowed_args [] = {
5584 { MP_QSTR_buffer , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = MP_OBJ_NULL } },
5685 { MP_QSTR_channel_count , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 1 } },
5786 { MP_QSTR_sample_rate , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 8000 } },
87+ { MP_QSTR_single_buffer , MP_ARG_BOOL | MP_ARG_KW_ONLY , {.u_bool = true} },
5888 };
5989 mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
6090 mp_arg_parse_all_kw_array (n_args , n_kw , all_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
@@ -69,9 +99,12 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a
6999 } else if (bufinfo .typecode != 'b' && bufinfo .typecode != 'B' && bufinfo .typecode != BYTEARRAY_TYPECODE ) {
70100 mp_raise_ValueError_varg (MP_ERROR_TEXT ("%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" ), MP_QSTR_buffer );
71101 }
102+ if (!args [ARG_single_buffer ].u_bool && bufinfo .len % (bytes_per_sample * args [ARG_channel_count ].u_int * 2 ) != 0 ) {
103+ mp_raise_ValueError_varg (MP_ERROR_TEXT ("Length of %q must be an even multiple of channel_count * type_size" ), MP_QSTR_buffer );
104+ }
72105 common_hal_audioio_rawsample_construct (self , ((uint8_t * )bufinfo .buf ), bufinfo .len ,
73106 bytes_per_sample , signed_samples , args [ARG_channel_count ].u_int ,
74- args [ARG_sample_rate ].u_int );
107+ args [ARG_sample_rate ].u_int , args [ ARG_single_buffer ]. u_bool );
75108
76109 return MP_OBJ_FROM_PTR (self );
77110}
0 commit comments