From 5542492d332719fb77765e7b97d4dc3cc07de765 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Thu, 20 Jun 2024 20:16:32 +0200 Subject: [PATCH] [xcode] Fix calculation of estimated wav sizes (causing M1001 crash) Fix regression from commit 3ee9204 where wav size calculation was changed. The new method caused Soundbridge M1001 to reboot, and the likely cause seems to be that the sizes in the wav header may not be multiples of channels x bytes_per_sample, so typically 4. Resolves #1770 --- src/transcode.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/transcode.c b/src/transcode.c index a58326e4..2b729df1 100644 --- a/src/transcode.c +++ b/src/transcode.c @@ -562,26 +562,22 @@ dummy_seek(void *arg, int64_t offset, enum transcode_seek_type type) } static off_t -size_estimate(enum transcode_profile profile, int bit_rate, int sample_rate, int bytes_per_sample, int channels, int len_ms) +size_estimate(enum transcode_profile profile, uint32_t bit_rate, uint32_t sample_rate, uint16_t bytes_per_sample, uint16_t channels, uint32_t len_ms) { - off_t bytes; + off_t bytes = 0; + uint64_t nsamples; - // If the source has a number of samples that doesn't match an even len_ms - // then the length may have been rounded up. We prefer an estimate that is on - // the low side, otherwise ffprobe won't trust the length from our wav header. - if (len_ms > 0) - len_ms -= 1; - else + if (len_ms == 0) len_ms = 3 * 60 * 1000; + nsamples = (uint64_t)sample_rate * (uint64_t)len_ms / 1000 + 1; // The +1 is to round up + if (profile == XCODE_WAV) - bytes = (int64_t)len_ms * channels * bytes_per_sample * sample_rate / 1000 + WAV_HEADER_LEN; + bytes = nsamples * channels * bytes_per_sample + WAV_HEADER_LEN; else if (profile == XCODE_MP3) - bytes = (int64_t)len_ms * bit_rate / 8000; + bytes = (uint64_t)len_ms * (uint64_t)bit_rate / 8000; else if (profile == XCODE_MP4_ALAC) - bytes = (int64_t)len_ms * channels * bytes_per_sample * sample_rate / 1000 / 2; // FIXME - else - bytes = -1; + bytes = nsamples * channels * bytes_per_sample / 2; // FIXME return bytes; } @@ -1095,24 +1091,22 @@ avio_evbuffer_close(AVIOContext *s) /* ----------------------- CUSTOM HEADER GENERATION ------------------------ */ static int -make_wav_header(struct evbuffer **wav_header, int sample_rate, int bytes_per_sample, int channels, off_t bytes_total) +make_wav_header(struct evbuffer **wav_header, uint32_t sample_rate, uint16_t bytes_per_sample, uint16_t channels, uint32_t bytes_total) { uint8_t header[WAV_HEADER_LEN]; - uint32_t wav_size = bytes_total - WAV_HEADER_LEN; - memcpy(header, "RIFF", 4); - add_le32(header + 4, 36 + wav_size); + add_le32(header + 4, bytes_total - 8); // Total file size - 8 bytes as defined by the format memcpy(header + 8, "WAVEfmt ", 8); add_le32(header + 16, 16); - add_le16(header + 20, 1); + add_le16(header + 20, 1); // AudioFormat (PCM) add_le16(header + 22, channels); /* channels */ add_le32(header + 24, sample_rate); /* samplerate */ add_le32(header + 28, sample_rate * channels * bytes_per_sample); /* byte rate */ add_le16(header + 32, channels * bytes_per_sample); /* block align */ add_le16(header + 34, 8 * bytes_per_sample); /* bits per sample */ memcpy(header + 36, "data", 4); - add_le32(header + 40, wav_size); + add_le32(header + 40, bytes_total - WAV_HEADER_LEN); *wav_header = evbuffer_new(); evbuffer_add(*wav_header, header, sizeof(header));