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 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.
30
41
//|
31
- //| Simple 8ksps 440 Hz sin wave ::
42
+ //| Playing 8ksps 440 Hz and 880 Hz sine waves ::
32
43
//|
44
+ //| import analogbufio
45
+ //| import array
33
46
//| import audiocore
34
- //| import audioio
47
+ //| import audiopwmio
35
48
//| import board
36
- //| import array
37
- //| import time
38
49
//| import math
50
+ //| import time
39
51
//|
40
- //| # Generate one period of sine wav .
52
+ //| # Generate one period of sine wave .
41
53
//| length = 8000 // 440
42
54
//| sine_wave = array.array("h", [0] * length)
43
55
//| for i in range(length):
44
56
//| 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)
45
58
//|
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()
49
68
//| 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()"""
51
80
//| ...
52
81
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 };
82
+ enum { ARG_buffer , ARG_channel_count , ARG_sample_rate , ARG_single_buffer };
54
83
static const mp_arg_t allowed_args [] = {
55
84
{ MP_QSTR_buffer , MP_ARG_OBJ | MP_ARG_REQUIRED , {.u_obj = MP_OBJ_NULL } },
56
85
{ MP_QSTR_channel_count , MP_ARG_INT | MP_ARG_KW_ONLY , {.u_int = 1 } },
57
86
{ 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} },
58
88
};
59
89
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
60
90
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
69
99
} else if (bufinfo .typecode != 'b' && bufinfo .typecode != 'B' && bufinfo .typecode != BYTEARRAY_TYPECODE ) {
70
100
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
101
}
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
+ }
72
105
common_hal_audioio_rawsample_construct (self , ((uint8_t * )bufinfo .buf ), bufinfo .len ,
73
106
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 );
75
108
76
109
return MP_OBJ_FROM_PTR (self );
77
110
}
0 commit comments