@ -18,7 +18,8 @@
Boston , MA 02110 - 1301 , USA .
Boston , MA 02110 - 1301 , USA .
*/
*/
// #define DEBUG
# define DEBUG
# define AKODE_MODULE "alsa_sink"
# include "akode_debug.h"
# include "akode_debug.h"
@ -172,6 +173,9 @@ found_format:
else
else
return - 1 ;
return - 1 ;
// Disable ALSA resampling, since we do that.
snd_pcm_hw_params_set_rate_resample ( m_data - > pcm_playback , hw , 0 ) ;
unsigned int rate = config - > sample_rate ;
unsigned int rate = config - > sample_rate ;
snd_pcm_hw_params_set_rate_near ( m_data - > pcm_playback , hw , & rate , 0 ) ;
snd_pcm_hw_params_set_rate_near ( m_data - > pcm_playback , hw , & rate , 0 ) ;
if ( m_data - > config . sample_rate ! = rate ) {
if ( m_data - > config . sample_rate ! = rate ) {
@ -181,25 +185,49 @@ found_format:
snd_pcm_hw_params_set_channels ( m_data - > pcm_playback , hw , config - > channels ) ;
snd_pcm_hw_params_set_channels ( m_data - > pcm_playback , hw , config - > channels ) ;
// Set up buffer parameters.
// This mainly fixes a delay with PulseAudio.
unsigned bufferTime = 100'000 ; // us (100ms)
unsigned periods = 4 ;
m_data - > fragmentSize = 1024 ;
int err = snd_pcm_hw_params_set_buffer_time_near ( m_data - > pcm_playback , hw , & bufferTime , nullptr ) ;
snd_pcm_uframes_t period_size = m_data - > fragmentSize / ( wid * config - > channels ) ;
if ( err < 0 )
snd_pcm_hw_params_set_period_size_near ( m_data - > pcm_playback , hw , & period_size , 0 ) ;
{
AKODE_WARN ( " unable to set buffer time: " < < snd_strerror ( err ) ) ;
}
if ( err > = 0 )
{
err = snd_pcm_hw_params_set_periods_near ( m_data - > pcm_playback , hw , & periods , nullptr ) ;
if ( err < 0 )
{
AKODE_WARN ( " unable to set periods near: " < < snd_strerror ( err ) ) ;
}
}
m_data - > fragmentSize = period_size * ( wid * config - > channels ) ;
err = snd_pcm_hw_params ( m_data - > pcm_playback , hw ) ;
// std::cerr << "akode: ALSA fragment-size: " << m_data->fragmentSize << "\n";
if ( err < 0 )
{
AKODE_WARN ( " unable to set hw params: " < < snd_strerror ( err ) ) ;
m_data - > error = true ;
return - 1 ;
}
snd_pcm_uframes_t bufferSize ;
snd_pcm_hw_params_get_buffer_size ( hw , & bufferSize ) ;
m_data - > fragmentSize = snd_pcm_frames_to_bytes ( m_data - > pcm_playback , bufferSize ) * 2 ;
delete m_data - > buffer ;
delete m_data - > buffer ;
m_data - > buffer = new char [ m_data - > fragmentSize ] ;
m_data - > buffer = new char [ m_data - > fragmentSize ] ;
m_data - > filled = 0 ;
m_data - > filled = 0 ;
if ( snd_pcm_hw_params ( m_data - > pcm_playback , hw ) < 0 ) {
m_data - > can_pause = ( snd_pcm_hw_params_can_pause ( hw ) = = 1 ) ;
return - 1 ;
}
AKODE_DEBUG ( " hw can-pause: " < < ( m_data - > can_pause ? " true " : " false " ) ) ;
else {
AKODE_DEBUG ( " buffer-size: " < < bufferSize < < " frames " ) ;
m_data - > can_pause = ( snd_pcm_hw_params_can_pause ( hw ) = = 1 ) ;
AKODE_DEBUG ( " fragment-size: " < <
return res ;
snd_pcm_bytes_to_frames ( m_data - > pcm_playback , m_data - > fragmentSize ) < < " frames " ) ;
}
return res ;
}
}
const AudioConfiguration * ALSASink : : audioConfiguration ( ) const
const AudioConfiguration * ALSASink : : audioConfiguration ( ) const