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[] = ...@@ -236,7 +236,7 @@ static const uint32_t pi_vlc_chan_order_wg4[] =
*/ */
VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *, VLC_API unsigned aout_CheckChannelReorder( const uint32_t *, const uint32_t *,
uint32_t mask, uint8_t *table ); 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 * This fonction will compute the extraction parameter into pi_selection to go
......
...@@ -44,9 +44,9 @@ struct aout_sys_t ...@@ -44,9 +44,9 @@ struct aout_sys_t
{ {
snd_pcm_t *pcm; snd_pcm_t *pcm;
unsigned rate; /**< Sample rate */ unsigned rate; /**< Sample rate */
vlc_fourcc_t format; /**< Sample format */
uint8_t chans_table[AOUT_CHAN_MAX]; /**< Channels order table */ uint8_t chans_table[AOUT_CHAN_MAX]; /**< Channels order table */
uint8_t chans_to_reorder; /**< Number of channels to reorder */ uint8_t chans_to_reorder; /**< Number of channels to reorder */
uint8_t bits; /**< Bits per sample per channel */
bool soft_mute; bool soft_mute;
float soft_gain; float soft_gain;
...@@ -563,11 +563,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt) ...@@ -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_bytes_per_frame = AOUT_SPDIF_SIZE;
fmt->i_frame_length = A52_FRAME_NB; fmt->i_frame_length = A52_FRAME_NB;
} }
else sys->format = fmt->i_format;
{
aout_FormatPrepare (fmt);
sys->bits = fmt->i_bitspersample;
}
aout->time_get = TimeGet; aout->time_get = TimeGet;
aout->play = Play; aout->play = Play;
...@@ -611,7 +607,7 @@ static void Play (audio_output_t *aout, block_t *block) ...@@ -611,7 +607,7 @@ static void Play (audio_output_t *aout, block_t *block)
if (sys->chans_to_reorder != 0) if (sys->chans_to_reorder != 0)
aout_ChannelReorder(block->p_buffer, block->i_buffer, 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; snd_pcm_t *pcm = sys->pcm;
......
...@@ -1222,7 +1222,7 @@ static void PlayAnalog (audio_output_t * p_aout, block_t * p_block) ...@@ -1222,7 +1222,7 @@ static void PlayAnalog (audio_output_t * p_aout, block_t * p_block)
p_block->i_buffer, p_block->i_buffer,
p_sys->chans_to_reorder, p_sys->chans_to_reorder,
p_sys->chan_table, p_sys->chan_table,
32); VLC_CODEC_FL32);
} }
/* Render audio into buffer */ /* Render audio into buffer */
......
...@@ -86,8 +86,7 @@ struct aout_sys_t ...@@ -86,8 +86,7 @@ struct aout_sys_t
uint8_t chans_to_reorder; /* do we need channel reordering */ uint8_t chans_to_reorder; /* do we need channel reordering */
uint8_t chan_table[AOUT_CHAN_MAX]; uint8_t chan_table[AOUT_CHAN_MAX];
uint32_t i_channel_mask; uint32_t i_channel_mask;
uint32_t i_bits_per_sample; vlc_fourcc_t format;
uint32_t i_channels;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -724,8 +723,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format, ...@@ -724,8 +723,7 @@ static int CreateDSBuffer( audio_output_t *p_aout, int i_format,
waveformat.Format.nAvgBytesPerSec = waveformat.Format.nAvgBytesPerSec =
waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign; waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign;
p_aout->sys->i_bits_per_sample = waveformat.Format.wBitsPerSample; p_aout->sys->format = i_format;
p_aout->sys->i_channels = i_nb_channels;
/* Then fill in the direct sound descriptor */ /* Then fill in the direct sound descriptor */
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
...@@ -903,7 +901,7 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer ) ...@@ -903,7 +901,7 @@ static int FillBuffer( audio_output_t *p_aout, int i_frame, block_t *p_buffer )
/* Do the channel reordering here */ /* Do the channel reordering here */
aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer, aout_ChannelReorder( p_buffer->p_buffer, p_buffer->i_buffer,
p_sys->chans_to_reorder, p_sys->chan_table, 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 ); memcpy( p_write_position, p_buffer->p_buffer, l_bytes1 );
block_Release( p_buffer ); block_Release( p_buffer );
......
...@@ -71,7 +71,7 @@ typedef struct aout_stream_sys ...@@ -71,7 +71,7 @@ typedef struct aout_stream_sys
uint8_t chans_table[AOUT_CHAN_MAX]; uint8_t chans_table[AOUT_CHAN_MAX];
uint8_t chans_to_reorder; uint8_t chans_to_reorder;
uint8_t bits; /**< Bits per sample */ vlc_fourcc_t format; /**< Sample format */
unsigned rate; /**< Sample rate */ unsigned rate; /**< Sample rate */
unsigned bytes_per_frame; unsigned bytes_per_frame;
UINT32 written; /**< Frames written to the buffer */ UINT32 written; /**< Frames written to the buffer */
...@@ -125,7 +125,7 @@ static HRESULT Play(aout_stream_t *s, block_t *block) ...@@ -125,7 +125,7 @@ static HRESULT Play(aout_stream_t *s, block_t *block)
if (sys->chans_to_reorder) if (sys->chans_to_reorder)
aout_ChannelReorder(block->p_buffer, block->i_buffer, 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); hr = IAudioClient_GetService(sys->client, &IID_IAudioRenderClient, &pv);
if (FAILED(hr)) if (FAILED(hr))
...@@ -356,7 +356,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, ...@@ -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_to_reorder = vlc_CheckWaveOrder((hr == S_OK) ? &wf.Format : pwf,
sys->chans_table); sys->chans_table);
sys->bits = fmt->i_bitspersample; sys->format = fmt->i_format;
hr = IAudioClient_Initialize(sys->client, AUDCLNT_SHAREMODE_SHARED, 0, hr = IAudioClient_Initialize(sys->client, AUDCLNT_SHAREMODE_SHARED, 0,
AOUT_MAX_PREPARE_TIME * 10, 0, AOUT_MAX_PREPARE_TIME * 10, 0,
......
...@@ -112,6 +112,7 @@ struct aout_sys_t ...@@ -112,6 +112,7 @@ struct aout_sys_t
uint8_t chans_to_reorder; /* do we need channel reordering */ uint8_t chans_to_reorder; /* do we need channel reordering */
uint8_t chan_table[AOUT_CHAN_MAX]; uint8_t chan_table[AOUT_CHAN_MAX];
vlc_fourcc_t format;
}; };
#include "volume.h" #include "volume.h"
...@@ -654,6 +655,7 @@ static int OpenWaveOut( audio_output_t *p_aout, uint32_t i_device_id, int i_form ...@@ -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 ); p_aout->sys->chan_table );
if( p_aout->sys->chans_to_reorder ) if( p_aout->sys->chans_to_reorder )
msg_Dbg( p_aout, "channel reordering needed" ); msg_Dbg( p_aout, "channel reordering needed" );
p_aout->sys->format = i_format;
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -917,8 +919,7 @@ static void* WaveOutThread( void *data ) ...@@ -917,8 +919,7 @@ static void* WaveOutThread( void *data )
aout_ChannelReorder( p_buffer->p_buffer, aout_ChannelReorder( p_buffer->p_buffer,
p_buffer->i_buffer, p_buffer->i_buffer,
p_sys->waveformat.Format.nChannels, p_sys->waveformat.Format.nChannels,
p_sys->chan_table, p_sys->chan_table, p_sys->format );
p_sys->waveformat.Format.wBitsPerSample );
} }
PlayWaveOut( p_aout, p_sys->h_waveout, PlayWaveOut( p_aout, p_sys->h_waveout,
......
...@@ -430,8 +430,7 @@ static int Demux( demux_t *p_demux ) ...@@ -430,8 +430,7 @@ static int Demux( demux_t *p_demux )
if( p_sys->i_chans_to_reorder ) if( p_sys->i_chans_to_reorder )
aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer, aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
p_sys->fmt.audio.i_channels, p_sys->fmt.audio.i_channels,
p_sys->pi_chan_table, p_sys->pi_chan_table, p_sys->fmt.i_codec );
p_sys->fmt.audio.i_bitspersample );
es_out_Send( p_demux->out, p_sys->p_es, p_block ); es_out_Send( p_demux->out, p_sys->p_es, p_block );
......
...@@ -293,8 +293,7 @@ static int Mux( sout_mux_t *p_mux ) ...@@ -293,8 +293,7 @@ static int Mux( sout_mux_t *p_mux )
if( p_sys->i_chans_to_reorder ) if( p_sys->i_chans_to_reorder )
aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer, aout_ChannelReorder( p_block->p_buffer, p_block->i_buffer,
p_sys->i_chans_to_reorder, p_sys->i_chans_to_reorder,
p_sys->pi_chan_table, p_sys->pi_chan_table, p_input->p_fmt->i_codec );
p_input->p_fmt->audio.i_bitspersample );
sout_AccessOutWrite( p_mux->p_access, p_block ); sout_AccessOutWrite( p_mux->p_access, p_block );
} }
......
...@@ -276,68 +276,130 @@ unsigned aout_CheckChannelReorder( const uint32_t *chans_in, ...@@ -276,68 +276,130 @@ unsigned aout_CheckChannelReorder( const uint32_t *chans_in,
return 0; 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, 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 ); 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++ ) for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j]; tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 4 * channels ); memcpy( buf, tmp, 4 * channels );
buf += channels; buf += channels;
} }
break; 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++ ) for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j]; tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, 2 * channels ); memcpy( buf, tmp, 2 * channels );
buf += channels; buf += channels;
} }
break; 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; 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]; uint8_t tmp[AOUT_CHAN_MAX];
for( size_t j = 0; j < channels; j++ ) for( size_t j = 0; j < channels; j++ )
tmp[chans_table[j]] = buf[j]; tmp[chans_table[j]] = buf[j];
memcpy( buf, tmp, channels ); memcpy( buf, tmp, channels );
buf += channels; buf += channels;
} }
break; 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