pcm_export: support DSD to DSD-over-USB conversion
Prepare for removing SAMPLE_FORMAT_DSD_OVER_USB.
This commit is contained in:
parent
f6d6110aaa
commit
ebfdd37451
@ -633,8 +633,9 @@ alsa_setup_or_dsd(struct alsa_data *ad, struct audio_format *audio_format,
|
|||||||
if (!success)
|
if (!success)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pcm_export_open(&ad->export, audio_format->format,
|
pcm_export_open(&ad->export,
|
||||||
packed, reverse_endian);
|
audio_format->format, audio_format->channels,
|
||||||
|
false, packed, reverse_endian);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,7 +778,8 @@ alsa_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
ad->period_position = (ad->period_position + ret)
|
ad->period_position = (ad->period_position + ret)
|
||||||
% ad->period_frames;
|
% ad->period_frames;
|
||||||
return ret * ad->in_frame_size;
|
return pcm_export_source_size(&ad->export,
|
||||||
|
ret * ad->in_frame_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
|
if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
|
||||||
|
@ -540,7 +540,7 @@ oss_probe_sample_format(int fd, enum sample_format sample_format,
|
|||||||
*oss_format_r = oss_format;
|
*oss_format_r = oss_format;
|
||||||
|
|
||||||
#ifdef AFMT_S24_PACKED
|
#ifdef AFMT_S24_PACKED
|
||||||
pcm_export_open(export, sample_format,
|
pcm_export_open(export, sample_format, 0, false,
|
||||||
oss_format == AFMT_S24_PACKED,
|
oss_format == AFMT_S24_PACKED,
|
||||||
oss_format == AFMT_S24_PACKED &&
|
oss_format == AFMT_S24_PACKED &&
|
||||||
G_BYTE_ORDER != G_LITTLE_ENDIAN);
|
G_BYTE_ORDER != G_LITTLE_ENDIAN);
|
||||||
@ -755,8 +755,12 @@ oss_output_play(struct audio_output *ao, const void *chunk, size_t size,
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ret = write(od->fd, chunk, size);
|
ret = write(od->fd, chunk, size);
|
||||||
if (ret > 0)
|
if (ret > 0) {
|
||||||
return (size_t)ret;
|
#ifdef AFMT_S24_PACKED
|
||||||
|
ret = pcm_export_source_size(&od->export, ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret < 0 && errno != EINTR) {
|
if (ret < 0 && errno != EINTR) {
|
||||||
g_set_error(error, oss_output_quark(), errno,
|
g_set_error(error, oss_output_quark(), errno,
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "pcm_export.h"
|
#include "pcm_export.h"
|
||||||
|
#include "pcm_dsd_usb.h"
|
||||||
#include "pcm_pack.h"
|
#include "pcm_pack.h"
|
||||||
#include "util/byte_reverse.h"
|
#include "util/byte_reverse.h"
|
||||||
|
|
||||||
@ -27,19 +28,31 @@ pcm_export_init(struct pcm_export_state *state)
|
|||||||
{
|
{
|
||||||
pcm_buffer_init(&state->reverse_buffer);
|
pcm_buffer_init(&state->reverse_buffer);
|
||||||
pcm_buffer_init(&state->pack_buffer);
|
pcm_buffer_init(&state->pack_buffer);
|
||||||
|
pcm_buffer_init(&state->dsd_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pcm_export_deinit(struct pcm_export_state *state)
|
void pcm_export_deinit(struct pcm_export_state *state)
|
||||||
{
|
{
|
||||||
pcm_buffer_deinit(&state->reverse_buffer);
|
pcm_buffer_deinit(&state->reverse_buffer);
|
||||||
pcm_buffer_deinit(&state->pack_buffer);
|
pcm_buffer_deinit(&state->pack_buffer);
|
||||||
|
pcm_buffer_deinit(&state->dsd_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pcm_export_open(struct pcm_export_state *state,
|
pcm_export_open(struct pcm_export_state *state,
|
||||||
enum sample_format sample_format,
|
enum sample_format sample_format, unsigned channels,
|
||||||
bool pack, bool reverse_endian)
|
bool dsd_usb, bool pack, bool reverse_endian)
|
||||||
{
|
{
|
||||||
|
assert(audio_valid_sample_format(sample_format));
|
||||||
|
assert(!dsd_usb || audio_valid_channel_count(channels));
|
||||||
|
|
||||||
|
state->channels = channels;
|
||||||
|
state->dsd_usb = dsd_usb && sample_format == SAMPLE_FORMAT_DSD;
|
||||||
|
if (state->dsd_usb)
|
||||||
|
/* after the conversion to DSD-over-USB, the DSD
|
||||||
|
samples are stuffed inside fake 24 bit samples */
|
||||||
|
sample_format = SAMPLE_FORMAT_S24_P32;
|
||||||
|
|
||||||
state->pack24 = pack && (sample_format == SAMPLE_FORMAT_S24_P32 || sample_format == SAMPLE_FORMAT_DSD_OVER_USB);
|
state->pack24 = pack && (sample_format == SAMPLE_FORMAT_S24_P32 || sample_format == SAMPLE_FORMAT_DSD_OVER_USB);
|
||||||
|
|
||||||
state->reverse_endian = 0;
|
state->reverse_endian = 0;
|
||||||
@ -58,6 +71,10 @@ const void *
|
|||||||
pcm_export(struct pcm_export_state *state, const void *data, size_t size,
|
pcm_export(struct pcm_export_state *state, const void *data, size_t size,
|
||||||
size_t *dest_size_r)
|
size_t *dest_size_r)
|
||||||
{
|
{
|
||||||
|
if (state->dsd_usb)
|
||||||
|
data = pcm_dsd_to_usb(&state->dsd_buffer, state->channels,
|
||||||
|
data, size, &size);
|
||||||
|
|
||||||
if (state->pack24) {
|
if (state->pack24) {
|
||||||
assert(size % 4 == 0);
|
assert(size % 4 == 0);
|
||||||
|
|
||||||
@ -90,3 +107,13 @@ pcm_export(struct pcm_export_state *state, const void *data, size_t size,
|
|||||||
*dest_size_r = size;
|
*dest_size_r = size;
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
pcm_export_source_size(const struct pcm_export_state *state, size_t size)
|
||||||
|
{
|
||||||
|
if (state->dsd_usb)
|
||||||
|
/* DSD over USB doubles the transport size */
|
||||||
|
size /= 2;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
@ -34,6 +34,14 @@ struct audio_format;
|
|||||||
* representation which are not supported by the pcm_convert library.
|
* representation which are not supported by the pcm_convert library.
|
||||||
*/
|
*/
|
||||||
struct pcm_export_state {
|
struct pcm_export_state {
|
||||||
|
/**
|
||||||
|
* The buffer is used to convert DSD samples to the
|
||||||
|
* DSD-over-USB format.
|
||||||
|
*
|
||||||
|
* @see #dsd_usb
|
||||||
|
*/
|
||||||
|
struct pcm_buffer dsd_buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The buffer is used to pack samples, removing padding.
|
* The buffer is used to pack samples, removing padding.
|
||||||
*
|
*
|
||||||
@ -48,6 +56,18 @@ struct pcm_export_state {
|
|||||||
*/
|
*/
|
||||||
struct pcm_buffer reverse_buffer;
|
struct pcm_buffer reverse_buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of channels.
|
||||||
|
*/
|
||||||
|
uint8_t channels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert DSD to DSD-over-USB? Input format must be
|
||||||
|
* SAMPLE_FORMAT_DSD and output format must be
|
||||||
|
* SAMPLE_FORMAT_S24_P32.
|
||||||
|
*/
|
||||||
|
bool dsd_usb;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pack 24 bit samples?
|
* Pack 24 bit samples?
|
||||||
*/
|
*/
|
||||||
@ -80,11 +100,13 @@ pcm_export_deinit(struct pcm_export_state *state);
|
|||||||
* times to reuse the object, until pcm_export_deinit() is called.
|
* times to reuse the object, until pcm_export_deinit() is called.
|
||||||
*
|
*
|
||||||
* This function cannot fail.
|
* This function cannot fail.
|
||||||
|
*
|
||||||
|
* @param channels the number of channels; ignored unless dsd_usb is set
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pcm_export_open(struct pcm_export_state *state,
|
pcm_export_open(struct pcm_export_state *state,
|
||||||
enum sample_format sample_format,
|
enum sample_format sample_format, unsigned channels,
|
||||||
bool pack, bool reverse_endian);
|
bool dsd_usb, bool pack, bool reverse_endian);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export a PCM buffer.
|
* Export a PCM buffer.
|
||||||
@ -99,4 +121,13 @@ const void *
|
|||||||
pcm_export(struct pcm_export_state *state, const void *src, size_t src_size,
|
pcm_export(struct pcm_export_state *state, const void *src, size_t src_size,
|
||||||
size_t *dest_size_r);
|
size_t *dest_size_r);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the number of consumed bytes from the pcm_export()
|
||||||
|
* destination buffer to the according number of bytes from the
|
||||||
|
* pcm_export() source buffer.
|
||||||
|
*/
|
||||||
|
G_GNUC_PURE
|
||||||
|
size_t
|
||||||
|
pcm_export_source_size(const struct pcm_export_state *state, size_t dest_size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user