mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-27 06:33:21 -05:00
[alsa] Fix playback of 24 bit audio (issue #830)
The player will write 24 bit samples using 3 bytes, not 4, so the appropriate sample format is SND_PCM_FORMAT_S24_3LE, not SND_PCM_FORMAT_S24_LE. For extra protection we also use snd_pcm_bytes_to_frames() instead of BTOS(), because that way we can be more certain that the buffer is not too short for snd_pcm_writei().
This commit is contained in:
parent
41f51d43ac
commit
85ab7c3057
@ -179,7 +179,7 @@ bps2format(int bits_per_sample)
|
|||||||
if (bits_per_sample == 16)
|
if (bits_per_sample == 16)
|
||||||
return SND_PCM_FORMAT_S16_LE;
|
return SND_PCM_FORMAT_S16_LE;
|
||||||
else if (bits_per_sample == 24)
|
else if (bits_per_sample == 24)
|
||||||
return SND_PCM_FORMAT_S24_LE;
|
return SND_PCM_FORMAT_S24_3LE;
|
||||||
else if (bits_per_sample == 32)
|
else if (bits_per_sample == 32)
|
||||||
return SND_PCM_FORMAT_S32_LE;
|
return SND_PCM_FORMAT_S32_LE;
|
||||||
else
|
else
|
||||||
@ -631,7 +631,7 @@ static int
|
|||||||
buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pcm_sframes_t avail)
|
buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pcm_sframes_t avail)
|
||||||
{
|
{
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t bufsize;
|
ssize_t bufsize;
|
||||||
size_t wrote;
|
size_t wrote;
|
||||||
snd_pcm_sframes_t nsamp;
|
snd_pcm_sframes_t nsamp;
|
||||||
snd_pcm_sframes_t ret;
|
snd_pcm_sframes_t ret;
|
||||||
@ -643,7 +643,7 @@ buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pc
|
|||||||
if (wrote < odata->bufsize)
|
if (wrote < odata->bufsize)
|
||||||
DPRINTF(E_WARN, L_LAUDIO, "Bug! Partial prebuf write %zu/%zu\n", wrote, odata->bufsize);
|
DPRINTF(E_WARN, L_LAUDIO, "Bug! Partial prebuf write %zu/%zu\n", wrote, odata->bufsize);
|
||||||
|
|
||||||
nsamp = BTOS(wrote, pb->quality.bits_per_sample, pb->quality.channels);
|
nsamp = snd_pcm_bytes_to_frames(pb->pcm, wrote);
|
||||||
return nsamp;
|
return nsamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,7 +651,7 @@ buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pc
|
|||||||
if (pb->prebuf.read_avail != 0)
|
if (pb->prebuf.read_avail != 0)
|
||||||
{
|
{
|
||||||
// Maximum amount of bytes we want to read
|
// Maximum amount of bytes we want to read
|
||||||
bufsize = STOB(avail, pb->quality.bits_per_sample, pb->quality.channels);
|
bufsize = snd_pcm_frames_to_bytes(pb->pcm, avail);
|
||||||
|
|
||||||
bufsize = ringbuffer_read(&buf, bufsize, &pb->prebuf);
|
bufsize = ringbuffer_read(&buf, bufsize, &pb->prebuf);
|
||||||
if (bufsize == 0)
|
if (bufsize == 0)
|
||||||
@ -659,7 +659,8 @@ buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pc
|
|||||||
|
|
||||||
// DPRINTF(E_DBG, L_LAUDIO, "Writing prebuffer (read_avail=%zu, bufsize=%zu, avail=%li)\n", pb->prebuf.read_avail, bufsize, avail);
|
// DPRINTF(E_DBG, L_LAUDIO, "Writing prebuffer (read_avail=%zu, bufsize=%zu, avail=%li)\n", pb->prebuf.read_avail, bufsize, avail);
|
||||||
|
|
||||||
nsamp = BTOS(bufsize, pb->quality.bits_per_sample, pb->quality.channels);
|
nsamp = snd_pcm_bytes_to_frames(pb->pcm, bufsize);
|
||||||
|
|
||||||
ret = snd_pcm_writei(pb->pcm, buf, nsamp);
|
ret = snd_pcm_writei(pb->pcm, buf, nsamp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -680,7 +681,9 @@ buffer_write(struct alsa_playback_session *pb, struct output_data *odata, snd_pc
|
|||||||
return odata->samples;
|
return odata->samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = snd_pcm_writei(pb->pcm, odata->buffer, odata->samples);
|
nsamp = snd_pcm_bytes_to_frames(pb->pcm, odata->bufsize);
|
||||||
|
|
||||||
|
ret = snd_pcm_writei(pb->pcm, odata->buffer, nsamp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -808,7 +811,7 @@ static int
|
|||||||
playback_drain(struct alsa_playback_session *pb)
|
playback_drain(struct alsa_playback_session *pb)
|
||||||
{
|
{
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t bufsize;
|
ssize_t bufsize;
|
||||||
snd_pcm_state_t state;
|
snd_pcm_state_t state;
|
||||||
snd_pcm_sframes_t avail;
|
snd_pcm_sframes_t avail;
|
||||||
snd_pcm_sframes_t delay;
|
snd_pcm_sframes_t delay;
|
||||||
@ -836,7 +839,7 @@ playback_drain(struct alsa_playback_session *pb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Maximum amount of bytes we want to read
|
// Maximum amount of bytes we want to read
|
||||||
bufsize = STOB(avail, pb->quality.bits_per_sample, pb->quality.channels);
|
bufsize = snd_pcm_frames_to_bytes(pb->pcm, avail);
|
||||||
|
|
||||||
bufsize = ringbuffer_read(&buf, bufsize, &pb->prebuf);
|
bufsize = ringbuffer_read(&buf, bufsize, &pb->prebuf);
|
||||||
if (bufsize == 0)
|
if (bufsize == 0)
|
||||||
@ -844,7 +847,7 @@ playback_drain(struct alsa_playback_session *pb)
|
|||||||
|
|
||||||
// DPRINTF(E_DBG, L_LAUDIO, "Draining prebuffer (read_avail=%zu, bufsize=%zu, avail=%li)\n", pb->prebuf.read_avail / 4, bufsize, avail);
|
// DPRINTF(E_DBG, L_LAUDIO, "Draining prebuffer (read_avail=%zu, bufsize=%zu, avail=%li)\n", pb->prebuf.read_avail / 4, bufsize, avail);
|
||||||
|
|
||||||
nsamp = BTOS(bufsize, pb->quality.bits_per_sample, pb->quality.channels);
|
nsamp = snd_pcm_bytes_to_frames(pb->pcm, bufsize);
|
||||||
|
|
||||||
ret = snd_pcm_writei(pb->pcm, buf, nsamp);
|
ret = snd_pcm_writei(pb->pcm, buf, nsamp);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user