Skip to content

Commit 13620cc

Browse files
committed
nRF: PWMAudioOut: fix half-speed playback of stereo samples
The "spacing" of "buffer structure" is confusing, use the "channel count" instead. Testing performed on nrf52840 feather: Play stereo and mono, 8- and 16-bit, 8kHz RawSamples representing 333.33Hz square waves. Use both mono and stereo PWMAudioOut instances. Scope the RC-filtered signal and use the scope's frequency measurement function, verify the frequency is 333 or 334Hz in all tested cases. In the "stereo output" cases, verify both the L and R channels. Verify the output amplitude is the same in both channels. In the "stereo output" cases, run a second test where the L channel's amplitude is attenuated 50%. Verify the output amplitude is correct in each channel.
1 parent f5e9131 commit 13620cc

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

ports/nrf/common-hal/audiopwmio/PWMAudioOut.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,27 +97,28 @@ STATIC void fill_buffers(audiopwmio_pwmaudioout_obj_t *self, int buf) {
9797
common_hal_audiopwmio_pwmaudioout_stop(self);
9898
return;
9999
}
100-
uint32_t num_samples = buffer_length / self->bytes_per_sample / self->spacing;
100+
uint32_t num_samples = buffer_length / self->bytes_per_sample / self->sample_channel_count;
101+
uint16_t *end_dev_buffer = dev_buffer + 2 * num_samples;
101102

102103
if (self->bytes_per_sample == 1) {
103104
uint8_t offset = self->signed_to_unsigned ? 0x80 : 0;
104105
uint16_t scale = self->scale;
105-
for (uint32_t i=0; i<buffer_length/self->spacing; i++) {
106+
while (dev_buffer < end_dev_buffer) {
106107
uint8_t rawval = (*buffer++ + offset);
107108
uint16_t val = (uint16_t)(((uint32_t)rawval * (uint32_t)scale) >> 8);
108109
*dev_buffer++ = val;
109-
if (self->spacing == 1)
110+
if (self->sample_channel_count == 1)
110111
*dev_buffer++ = val;
111112
}
112113
} else {
113114
uint16_t offset = self->signed_to_unsigned ? 0x8000 : 0;
114115
uint16_t scale = self->scale;
115116
uint16_t *buffer16 = (uint16_t*)buffer;
116-
for (uint32_t i=0; i<buffer_length/2/self->spacing; i++) {
117+
while (dev_buffer < end_dev_buffer) {
117118
uint16_t rawval = (*buffer16++ + offset);
118119
uint16_t val = (uint16_t)((rawval * (uint32_t)scale) >> 16);
119120
*dev_buffer++ = val;
120-
if (self->spacing == 1)
121+
if (self->sample_channel_count == 1)
121122
*dev_buffer++ = val;
122123
}
123124
}
@@ -231,9 +232,12 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t* self,
231232
self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8;
232233

233234
uint32_t max_buffer_length;
235+
uint8_t spacing;
234236
audiosample_get_buffer_structure(sample, /* single channel */ false,
235237
&self->single_buffer, &self->signed_to_unsigned, &max_buffer_length,
236-
&self->spacing);
238+
&spacing);
239+
self->sample_channel_count = audiosample_channel_count(sample);
240+
237241
if (max_buffer_length > UINT16_MAX) {
238242
mp_raise_ValueError_varg(translate("Buffer length %d too big. It must be less than %d"), max_buffer_length, UINT16_MAX);
239243
}

ports/nrf/common-hal/audiopwmio/PWMAudioOut.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ typedef struct {
4141

4242
uint8_t left_channel_number;
4343
uint8_t right_channel_number;
44-
uint8_t spacing;
44+
uint8_t sample_channel_count;
4545
uint8_t bytes_per_sample;
4646

4747
bool playing;

0 commit comments

Comments
 (0)