Commit 980f2ca5 authored by Max Kellermann's avatar Max Kellermann

output_buffer: don't split frames

Splitting a frame between two buffer chunks causes distortion in the output. MPD used to assume that the chunk size 1020 would never cause splitted frames, but that isn't the case for 24 bit stereo (127.5 frames), and even less for files with even more channels.
parent 4f807b3a
......@@ -254,6 +254,9 @@ int playAudio(const char *buffer, size_t length)
int ret = -1, err;
unsigned int i;
/* no partial frames allowed */
assert((length % audio_format_frame_size(&input_audio_format)) == 0);
syncAudioDeviceStates();
for (i = 0; i < audioOutputArraySize; ++i)
......
......@@ -154,12 +154,13 @@ ob_chunk * ob_get_chunk(const unsigned i)
*/
static ob_chunk *tail_chunk(float data_time, uint16_t bitRate)
{
const size_t frame_size = audio_format_frame_size(&ob.audioFormat);
unsigned int next;
ob_chunk *chunk;
chunk = ob_get_chunk(ob.end);
assert(chunk->chunkSize <= sizeof(chunk->data));
if (chunk->chunkSize == sizeof(chunk->data)) {
if (chunk->chunkSize + frame_size > sizeof(chunk->data)) {
/* this chunk is full; allocate a new chunk */
next = successor(ob.end);
if (ob.begin == next)
......@@ -186,9 +187,13 @@ size_t ob_append(const void *data0, size_t datalen,
float data_time, uint16_t bitRate)
{
const unsigned char *data = data0;
const size_t frame_size = audio_format_frame_size(&ob.audioFormat);
size_t ret = 0, dataToSend;
ob_chunk *chunk = NULL;
/* no partial frames allowed */
assert((datalen % frame_size) == 0);
while (datalen) {
chunk = tail_chunk(data_time, bitRate);
if (chunk == NULL)
......@@ -198,6 +203,10 @@ size_t ob_append(const void *data0, size_t datalen,
if (dataToSend > datalen)
dataToSend = datalen;
/* don't split frames */
dataToSend /= frame_size;
dataToSend *= frame_size;
memcpy(chunk->data + chunk->chunkSize, data, dataToSend);
chunk->chunkSize += dataToSend;
datalen -= dataToSend;
......
......@@ -560,6 +560,9 @@ size_t pcm_convert_size(const struct audio_format *inFormat, size_t src_size,
const int shift = 2 * outFormat->channels;
size_t dest_size = src_size;
/* no partial frames allowed */
assert((src_size % audio_format_frame_size(inFormat)) == 0);
switch (inFormat->bits) {
case 8:
dest_size <<= 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment