17
17
//| """A raw audio sample buffer in memory"""
18
18
//|
19
19
//| 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
21
26
//| ) -> None:
22
27
//| """Create a RawSample based on the given buffer of values. If channel_count is more than
23
28
//| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the
27
32
//| :param ~circuitpython_typing.ReadableBuffer buffer: A buffer with samples
28
33
//| :param int channel_count: The number of channels in the buffer
29
34
//| :param int sample_rate: The desired playback sample rate
35
+ //| :param bool single_buffer: Selects single buffered or double buffered transfer mode. This affects
36
+ //| what happens if the sample buffer is changed while the sample is playing.
37
+ //| In single buffered transfers, a change in buffer contents will not affect active playback.
38
+ //| In double buffered transfers, changed buffer contents will
39
+ //| be played back when the transfer reaches the next half-buffer point.
30
40
//|
31
- //| Simple 8ksps 440 Hz sin wave ::
41
+ //| Playing 8ksps 440 Hz and 880 Hz sine waves ::
32
42
//|
43
+ //| import analogbufio
44
+ //| import array
33
45
//| import audiocore
34
- //| import audioio
46
+ //| import audiopwmio
35
47
//| import board
36
- //| import array
37
- //| import time
38
48
//| import math
49
+ //| import time
39
50
//|
40
- //| # Generate one period of sine wav .
51
+ //| # Generate one period of sine wave .
41
52
//| length = 8000 // 440
42
53
//| sine_wave = array.array("h", [0] * length)
43
54
//| for i in range(length):
44
55
//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
56
+ //| pwm = audiopwmio.PWMAudioOut(left_channel=board.D12, right_channel=board.D13)
45
57
//|
46
- //| dac = audioio.AudioOut(board.SPEAKER)
47
- //| sine_wave = audiocore.RawSample(sine_wave)
48
- //| dac.play(sine_wave, loop=True)
58
+ //| # Play single-buffered
59
+ //| sample = audiocore.RawSample(sine_wave)
60
+ //| pwm.play(sample, loop=True)
61
+ //| time.sleep(3)
62
+ //| # changing the wave has no effect
63
+ //| for i in range(length):
64
+ //| sine_wave[i] = int(math.sin(math.pi * 4 * i / length) * (2 ** 15))
65
+ //| time.sleep(3)
66
+ //| pwm.stop()
49
67
//| time.sleep(1)
50
- //| dac.stop()"""
68
+ //|
69
+ //| # Play double-buffered
70
+ //| sample = audiocore.RawSample(sine_wave, single_buffer=False)
71
+ //| pwm.play(sample, loop=True)
72
+ //| time.sleep(3)
73
+ //| # changing the wave takes effect almost immediately
74
+ //| for i in range(length):
75
+ //| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15))
76
+ //| time.sleep(3)
77
+ //| pwm.stop()
78
+ //| pwm.deinit()"""
51
79
//| ...
52
80
static 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 };
81
+ enum { ARG_buffer , ARG_channel_count , ARG_sample_rate , ARG_single_buffer };
54
82
static const mp_arg_t allowed_args [] = {
55
83
{ MP_QSTR_buffer , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = MP_OBJ_NULL } },
56
84
{ MP_QSTR_channel_count , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 1 } },
57
85
{ MP_QSTR_sample_rate , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 8000 } },
86
+ { MP_QSTR_single_buffer , MP_ARG_BOOL | MP_ARG_KW_ONLY , {.u_bool = true} },
58
87
};
59
88
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
60
89
mp_arg_parse_all_kw_array (n_args , n_kw , all_args , MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
@@ -69,9 +98,12 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a
69
98
} else if (bufinfo .typecode != 'b' && bufinfo .typecode != 'B' && bufinfo .typecode != BYTEARRAY_TYPECODE ) {
70
99
mp_raise_ValueError_varg (MP_ERROR_TEXT ("%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" ), MP_QSTR_buffer );
71
100
}
101
+ if (!args [ARG_single_buffer ].u_bool && bufinfo .len % (bytes_per_sample * args [ARG_channel_count ].u_int * 2 ) != 0 ) {
102
+ mp_raise_ValueError_varg (MP_ERROR_TEXT ("Length of %q must be an even multiple of channel_count * type_size" ), MP_QSTR_buffer );
103
+ }
72
104
common_hal_audioio_rawsample_construct (self , ((uint8_t * )bufinfo .buf ), bufinfo .len ,
73
105
bytes_per_sample , signed_samples , args [ARG_channel_count ].u_int ,
74
- args [ARG_sample_rate ].u_int );
106
+ args [ARG_sample_rate ].u_int , args [ ARG_single_buffer ]. u_bool );
75
107
76
108
return MP_OBJ_FROM_PTR (self );
77
109
}
0 commit comments