Commit 51087cc2 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: pass FOURCC instead of bits to aout_ChannelsReorder()

To fix type aliasing, we need to know whether the data is float or integer,
or use only char pointers.

Also add support for FL64 and arbitrary lengths.
parent 8d73a4d7
......@@ -236,7 +236,7 @@ static const uint32_t pi_vlc_chan_order_wg4[] =
*/
VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *,
uint32_t mask, uint8_t *table );
VLC_API void aout_ChannelReorder( void *, size_t, unsigned, const uint8_t *, unsigned );
VLC_API void aout_ChannelReorder(void *, size_t, unsigned, const uint8_t *, vlc_fourcc_t);
/**
* This fonction will compute the extraction parameter into pi_selection to go
......
......@@ -44,9 +44,9 @@ struct aout_sys_t
{
snd_pcm_t *pcm;
unsigned rate; /**< Sample rate */
vlc_fourcc_t format; /**< Sample format */
uint8_t chans_table[AOUT_CHAN_MAX]; /**< Channels order table */
uint8_t chans_to_reorder; /**< Number of channels to reorder */
uint8_t bits; /**< Bits per sample per channel */
bool soft_mute;
float soft_gain;
......@@ -563,11 +563,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB;
}
else
{
aout_FormatPrepare (fmt);
sys->bits = fmt->i_bitspersample;
}
sys->format = fmt->i_format;
aout->time_get = TimeGet;
aout->play = Play;
......@@ -611,7 +607,7 @@ static void Play (audio_output_t *aout, block_t *block)
if (sys->chans_to_reorder != 0)
aout_ChannelReorder(block->p_buffer, block->i_buffer,
sys->chans_to_reorder, sys->chans_table, sys->bits);
sys->chans_to_reorder, sys->chans_table, sys->format);
snd_pcm_t *pcm = sys->pcm;
......
......@@ -1222,7 +1222,7 @@ static void PlayAnalog (audio_output_t * p_aout, block_t * p_block)
p_block->i_buffer,
p_sys->chans_to_reorder,
p_sys->chan_table,
32);
VLC_CODEC_FL32);
}
/* Render audio into buffer */
......
......@@ -86,8 +86,7 @@ struct aout_sys_t
uint8_t chans_to_reorder; /* do we need channel reordering */
uint8_t chan_table[AOUT_CHAN_MAX];
uint32_t i_channel_mask;
uint32_t i_bits_per_sample;
uint32_t i_channels;
vlc_fourcc_t format;
};
/*****************************************************************************
......@@ -724,8 +723,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
waveformat.Format.nAvgBytesPerSec =
waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
p_aout->sys->i_bits_per_sample = waveformat.Format.wBitsPerSample;
p_aout->sys->i_channels = i_nb_channels;
p_aout->sys->format = i_format;
/* Then fill in the direct sound descriptor */
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
......@@ -903,7 +901,7 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
/* Do the channel reordering here */
aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
p_sys->chans_to_reorder, p_sys->chan_table,
p_sys->i_bits_per_sample );
p_sys->format );
memcpy( p_write_position, p_buffer->p_buffer, l_bytes1 );
block_Release( p_buffer );
......
......@@ -71,7 +71,7 @@ typedef struct aout_stream_sys
uint8_t chans_table[AOUT_CHAN_MAX];
uint8_t chans_to_reorder;
uint8_t bits; /**< Bits per sample */
vlc_fourcc_t format; /**< Sample format */
unsigned rate; /**< Sample rate */
unsigned bytes_per_frame;
UINT32 written; /**< Frames written to the buffer */
......@@ -125,7 +125,7 @@ static HRESULT Play(aout_stream_t *s, block_t *block)
if (sys->chans_to_reorder)
aout_ChannelReorder(block->p_buffer, block->i_buffer,
sys->chans_to_reorder, sys->chans_table, sys->bits);
sys->chans_to_reorder, sys->chans_table, sys->format);
hr = IAudioClient_GetService(sys->client, &IID_IAudioRenderClient, &pv);
if (FAILED(hr))
......@@ -356,7 +356,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt,
sys->chans_to_reorder = vlc_CheckWaveOrder((hr == S_OK) ? &wf.Format : pwf,
sys->chans_table);
sys->bits = fmt->i_bitspersample;
sys->format = fmt->i_format;
hr = IAudioClient_Initialize(sys->client, AUDCLNT_SHAREMODE_SHARED, 0,
AOUT_MAX_PREPARE_TIME * 10, 0,
......
......@@ -112,6 +112,7 @@ struct aout_sys_t
uint8_t chans_to_reorder; /* do we need channel reordering */
uint8_t chan_table[AOUT_CHAN_MAX];
vlc_fourcc_t format;
};
#include "volume.h"
......@@ -654,6 +655,7 @@ static int OpenWaveOut( audio_output_t *p_aout, uint32_t i_device_id, int i_form
p_aout->sys->chan_table );
if( p_aout->sys->chans_to_reorder )
msg_Dbg( p_aout, "channel reordering needed" );
p_aout->sys->format = i_format;
return VLC_SUCCESS;
......@@ -917,8 +919,7 @@ static void* WaveOutThread( void *data )
aout_ChannelReorder( p_buffer->p_buffer,
p_buffer->i_buffer,
p_sys->waveformat.Format.nChannels,
p_sys->chan_table,
p_sys->waveformat.Format.wBitsPerSample );
p_sys->chan_table, p_sys->format );
}
PlayWaveOut( p_aout, p_sys->h_waveout,
......
......@@ -430,8 +430,7 @@ static int Demux( demux_t *p_demux )
if( p_sys->i_chans_to_reorder )
aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
p_sys->fmt.audio.i_channels,
p_sys->pi_chan_table,
p_sys->fmt.audio.i_bitspersample );
p_sys->pi_chan_table, p_sys->fmt.i_codec );
es_out_Send( p_demux->out, p_sys->p_es, p_block );
......
......@@ -293,8 +293,7 @@ static int Mux( sout_mux_t *p_mux )
if( p_sys->i_chans_to_reorder )
aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
p_sys->i_chans_to_reorder,
p_sys->pi_chan_table,
p_input->p_fmt->audio.i_bitspersample );
p_sys->pi_chan_table, p_input->p_fmt->i_codec );
sout_AccessOutWrite( p_mux->p_access, p_block );
}
......
......@@ -276,68 +276,130 @@ unsigned aout_CheckChannelReorder( const uint32_t *chans_in,
return 0;
}
/*****************************************************************************
* aout_ChannelReorder :
*****************************************************************************/
/**
* Reorders audio samples within a block of linear audio interleaved samples.
* \param ptr start address of the block of samples
* \param bytes size of the block in bytes (must be a multiple of the product of the
* channels count and the sample size)
* \param channels channels count (also length of the chans_table table)
* \param chans_table permutation table to reorder the channels
* (usually computed by aout_CheckChannelReorder())
* \param fourcc sample format (must be a linear sample format)
* \note The samples must be naturally aligned in memory.
*/
void aout_ChannelReorder( void *ptr, size_t bytes, unsigned channels,
const uint8_t *chans_table, unsigned bits_per_sample )
const uint8_t *restrict chans_table, vlc_fourcc_t fourcc )
{
size_t samples = bytes / (channels * (bits_per_sample >> 3));
assert( channels != 0 );
assert( channels <= AOUT_CHAN_MAX );
switch( bits_per_sample )
/* The audio formats supported in audio output are inlined. For other formats (used in
* demuxers and muxers), memcpy() is used to avoid breaking type punning. */
switch( fourcc )
{
case 32:
case VLC_CODEC_FL32:
{
uint32_t *buf = ptr;
const size_t frames = (bytes / 4) / channels;
float *buf = ptr;
for( size_t i = 0; i < samples; i++ )
for( size_t i = 0; i < frames; i++ )
{
uint32_t tmp[AOUT_CHAN_MAX];
float tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 4 * channels );
buf += channels;
}
break;
}
case 16:
case VLC_CODEC_S16N:
{
uint16_t *buf = ptr;
const size_t frames = (bytes / 2) / channels;
int16_t *buf = ptr;
for( size_t i = 0; i < samples; i++ )
for( size_t i = 0; i < frames; i++ )
{
uint16_t tmp[AOUT_CHAN_MAX];
int16_t tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 2 * channels );
buf += channels;
}
break;
}
case 8:
case VLC_CODEC_FL64:
{
const size_t frames = (bytes / 8) / channels;
double *buf = ptr;
for( size_t i = 0; i < frames; i++ )
{
double tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 8 * channels );
buf += channels;
}
break;
}
case VLC_CODEC_S32N:
{
const size_t frames = (bytes / 4) / channels;
int32_t *buf = ptr;
for( size_t i = 0; i < frames; i++ )
{
int32_t tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 4 * channels );
buf += channels;
}
break;
}
case VLC_CODEC_U8:
{
const size_t frames = bytes / channels;
uint8_t *buf = ptr;
for( size_t i = 0; i < samples; i++ )
for( size_t i = 0; i < frames; i++ )
{
uint8_t tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, channels );
buf += channels;
}
break;
}
default:
{
unsigned size = aout_BitsPerSample( fourcc ) / 8;
const size_t frames = bytes / size;
unsigned char *buf = ptr;
assert( bytes != 0 );
for( size_t i = 0; i < frames; i++ )
{
unsigned char tmp[AOUT_CHAN_MAX * bytes];
for( size_t j = 0; j < channels; j++ )
memcpy( tmp + size * chans_table[j], buf + size * j, size );
memcpy( buf, tmp, size * channels );
buf += size * channels;
}
break;
}
}
}
......
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