aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-10-23 16:48:49 +0200
committerMax Kellermann <max@duempel.org>2008-10-23 16:48:49 +0200
commit980f2ca56dbedb60aa3f880f66a97d151a107e62 (patch)
treeea209a4c759052d0fba121939edb2b0de9bdb7fc
parent4f807b3aaa9617dfc35fb73ec898c8c9a22fded4 (diff)
downloadmpd-980f2ca56dbedb60aa3f880f66a97d151a107e62.tar.gz
mpd-980f2ca56dbedb60aa3f880f66a97d151a107e62.tar.xz
mpd-980f2ca56dbedb60aa3f880f66a97d151a107e62.zip
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.
-rw-r--r--src/audio.c3
-rw-r--r--src/outputBuffer.c11
-rw-r--r--src/pcm_utils.c3
3 files changed, 16 insertions, 1 deletions
diff --git a/src/audio.c b/src/audio.c
index 4305235d0..7d8e49f77 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -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)
diff --git a/src/outputBuffer.c b/src/outputBuffer.c
index 88191fd18..932ffd032 100644
--- a/src/outputBuffer.c
+++ b/src/outputBuffer.c
@@ -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;
diff --git a/src/pcm_utils.c b/src/pcm_utils.c
index 5d315bdb3..bd7fc0482 100644
--- a/src/pcm_utils.c
+++ b/src/pcm_utils.c
@@ -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;