Handle hardware that only supports 48khz output (eg. Intel8x0, on
nForce boards). Allow drivers to tell whether specific sample rates are supported (instead of "all or nothing"). Warning: this will break the Windows (and possibly OS X) drivers for a few minutes until I update them.
This commit is contained in:
@@ -11,6 +11,21 @@
|
|||||||
#define ALSA_ASSERT(x) \
|
#define ALSA_ASSERT(x) \
|
||||||
if (err < 0) { LOG->Warn("ALSA9: %s: %s", x, dsnd_strerror(err)); }
|
if (err < 0) { LOG->Warn("ALSA9: %s: %s", x, dsnd_strerror(err)); }
|
||||||
|
|
||||||
|
/* If the given sample rate can be used, return it. Otherwise, return the
|
||||||
|
* samplerate to use instead. */
|
||||||
|
unsigned Alsa9Buf::FindSampleRate( unsigned rate )
|
||||||
|
{
|
||||||
|
snd_pcm_hw_params_t *testhw;
|
||||||
|
dsnd_pcm_hw_params_alloca( &testhw );
|
||||||
|
dsnd_pcm_hw_params_any( pcm, testhw );
|
||||||
|
|
||||||
|
int err = dsnd_pcm_hw_params_set_rate_near(pcm, testhw, &rate, 0);
|
||||||
|
if( err >= 0 )
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool Alsa9Buf::SetHWParams()
|
bool Alsa9Buf::SetHWParams()
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
@@ -45,11 +60,7 @@ bool Alsa9Buf::SetHWParams()
|
|||||||
err = dsnd_pcm_hw_params_set_channels(pcm, hwparams, 2);
|
err = dsnd_pcm_hw_params_set_channels(pcm, hwparams, 2);
|
||||||
ALSA_CHECK("dsnd_pcm_hw_params_set_channels");
|
ALSA_CHECK("dsnd_pcm_hw_params_set_channels");
|
||||||
|
|
||||||
/* Set the sample rate. We shouldn't need to set it if rate is DYNAMIC_SAMPLERATE,
|
/* Set the sample rate. */
|
||||||
* but I've had alsalib crashes if I don't. */
|
|
||||||
if( samplerate == Alsa9Buf::DYNAMIC_SAMPLERATE )
|
|
||||||
samplerate = 44100;
|
|
||||||
|
|
||||||
unsigned int rate = samplerate;
|
unsigned int rate = samplerate;
|
||||||
err = dsnd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, 0);
|
err = dsnd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, 0);
|
||||||
ALSA_CHECK("dsnd_pcm_hw_params_set_rate_near");
|
ALSA_CHECK("dsnd_pcm_hw_params_set_rate_near");
|
||||||
@@ -139,21 +150,21 @@ void Alsa9Buf::ErrorHandler(const char *file, int line, const char *function, in
|
|||||||
/* NOP */
|
/* NOP */
|
||||||
}
|
}
|
||||||
|
|
||||||
Alsa9Buf::Alsa9Buf( hw hardware, int channels_, int samplerate_ )
|
Alsa9Buf::Alsa9Buf( hw hardware, int channels_ )
|
||||||
{
|
{
|
||||||
GetSoundCardDebugInfo();
|
GetSoundCardDebugInfo();
|
||||||
|
|
||||||
dsnd_lib_error_set_handler( ErrorHandler );
|
dsnd_lib_error_set_handler( ErrorHandler );
|
||||||
|
|
||||||
channels = channels_;
|
channels = channels_;
|
||||||
samplerate = samplerate_;
|
samplerate = 44100;
|
||||||
samplebits = 16;
|
samplebits = 16;
|
||||||
last_cursor_pos = 0;
|
last_cursor_pos = 0;
|
||||||
|
|
||||||
/* Open the device. */
|
/* Open the device. */
|
||||||
int err;
|
int err;
|
||||||
// err = dsnd_pcm_open( &pcm, "dmix", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK );
|
// err = dsnd_pcm_open( &pcm, "dmix", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK );
|
||||||
err = dsnd_pcm_open( &pcm, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK );
|
err = dsnd_pcm_open( &pcm, "hw:0", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK );
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
RageException::ThrowNonfatal("dsnd_pcm_open: %s", dsnd_strerror(err));
|
RageException::ThrowNonfatal("dsnd_pcm_open: %s", dsnd_strerror(err));
|
||||||
|
|
||||||
@@ -251,7 +262,7 @@ void Alsa9Buf::Write( const Sint16 *buffer, int frames )
|
|||||||
|
|
||||||
last_cursor_pos += wrote;
|
last_cursor_pos += wrote;
|
||||||
if( wrote < frames )
|
if( wrote < frames )
|
||||||
LOG->Trace("Couldn't write whole buffer? (%i < %i)\n", wrote, frames );
|
LOG->Trace("Couldn't write whole buffer? (%i < %i)", wrote, frames );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,14 +28,13 @@ public:
|
|||||||
|
|
||||||
enum hw { HW_HARDWARE, HW_SOFTWARE, HW_DONT_CARE };
|
enum hw { HW_HARDWARE, HW_SOFTWARE, HW_DONT_CARE };
|
||||||
|
|
||||||
/* If samplerate is DYNAMIC_SAMPLERATE, then call SetSampleRate before
|
/* Call SetSampleRate before you use the sample. */
|
||||||
* you use the sample. */
|
Alsa9Buf( hw hardware, int channels );
|
||||||
enum { DYNAMIC_SAMPLERATE = -1 };
|
|
||||||
Alsa9Buf( hw hardware, int channels, int samplerate );
|
|
||||||
~Alsa9Buf();
|
~Alsa9Buf();
|
||||||
|
|
||||||
int GetNumFramesToFill( int writeahead );
|
int GetNumFramesToFill( int writeahead );
|
||||||
void Write( const Sint16 *buffer, int frames );
|
void Write( const Sint16 *buffer, int frames );
|
||||||
|
unsigned FindSampleRate( unsigned rate );
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Play();
|
void Play();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ protected:
|
|||||||
* get it. */
|
* get it. */
|
||||||
virtual void VolumeChanged() { }
|
virtual void VolumeChanged() { }
|
||||||
|
|
||||||
virtual int GetSampleRate() const { return 44100; }
|
virtual int GetSampleRate( int rate ) const { return 44100; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~RageSoundDriver() { }
|
virtual ~RageSoundDriver() { }
|
||||||
|
|||||||
@@ -208,6 +208,14 @@ int RageSound_ALSA9::GetPosition(const RageSound *snd) const
|
|||||||
return stream_pool[i]->pcm->GetPosition();
|
return stream_pool[i]->pcm->GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RageSound_ALSA9::GetSampleRate( int rate ) const
|
||||||
|
{
|
||||||
|
LockMutex L(SOUNDMAN->lock);
|
||||||
|
|
||||||
|
stream *str = stream_pool[0];
|
||||||
|
return str->pcm->FindSampleRate( rate );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RageSound_ALSA9::RageSound_ALSA9()
|
RageSound_ALSA9::RageSound_ALSA9()
|
||||||
{
|
{
|
||||||
@@ -222,7 +230,7 @@ try {
|
|||||||
{
|
{
|
||||||
Alsa9Buf *newbuf;
|
Alsa9Buf *newbuf;
|
||||||
try {
|
try {
|
||||||
newbuf = new Alsa9Buf( Alsa9Buf::HW_HARDWARE, channels, Alsa9Buf::DYNAMIC_SAMPLERATE );
|
newbuf = new Alsa9Buf( Alsa9Buf::HW_HARDWARE, channels );
|
||||||
} catch(const RageException &e) {
|
} catch(const RageException &e) {
|
||||||
/* If we didn't get at least 8, fail. */
|
/* If we didn't get at least 8, fail. */
|
||||||
if(i >= 8) break; /* OK */
|
if(i >= 8) break; /* OK */
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public:
|
|||||||
void StartMixing(RageSound *snd);
|
void StartMixing(RageSound *snd);
|
||||||
void StopMixing(RageSound *snd);
|
void StopMixing(RageSound *snd);
|
||||||
int GetPosition(const RageSound *snd) const;
|
int GetPosition(const RageSound *snd) const;
|
||||||
int GetSampleRate() const { return -1; }
|
int GetSampleRate( int rate ) const;
|
||||||
|
|
||||||
void Update(float delta);
|
void Update(float delta);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
const int channels = 2;
|
const int channels = 2;
|
||||||
const int samplerate = 44100;
|
int samplerate = 44100;
|
||||||
|
|
||||||
const int samples_per_frame = channels;
|
const int samples_per_frame = channels;
|
||||||
const int bytes_per_frame = sizeof(Sint16) * samples_per_frame;
|
const int bytes_per_frame = sizeof(Sint16) * samples_per_frame;
|
||||||
@@ -176,7 +176,10 @@ try {
|
|||||||
if( PREFSMAN->m_iSoundWriteAhead )
|
if( PREFSMAN->m_iSoundWriteAhead )
|
||||||
max_writeahead = PREFSMAN->m_iSoundWriteAhead;
|
max_writeahead = PREFSMAN->m_iSoundWriteAhead;
|
||||||
|
|
||||||
pcm = new Alsa9Buf( Alsa9Buf::HW_DONT_CARE, channels, samplerate );
|
pcm = new Alsa9Buf( Alsa9Buf::HW_DONT_CARE, channels );
|
||||||
|
|
||||||
|
samplerate = pcm->FindSampleRate( samplerate );
|
||||||
|
pcm->SetSampleRate( samplerate );
|
||||||
|
|
||||||
MixingThread.SetName( "RageSound_ALSA9_Software" );
|
MixingThread.SetName( "RageSound_ALSA9_Software" );
|
||||||
MixingThread.Create( MixerThread_start, this );
|
MixingThread.Create( MixerThread_start, this );
|
||||||
@@ -205,6 +208,11 @@ float RageSound_ALSA9_Software::GetPlayLatency() const
|
|||||||
return float(max_writeahead)/samplerate;
|
return float(max_writeahead)/samplerate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RageSound_ALSA9_Software::GetSampleRate( int rate ) const
|
||||||
|
{
|
||||||
|
return samplerate;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002 by the person(s) listed below. All rights reserved.
|
* Copyright (c) 2002 by the person(s) listed below. All rights reserved.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ public:
|
|||||||
void StopMixing(RageSound *snd);
|
void StopMixing(RageSound *snd);
|
||||||
int GetPosition(const RageSound *snd) const;
|
int GetPosition(const RageSound *snd) const;
|
||||||
float GetPlayLatency() const;
|
float GetPlayLatency() const;
|
||||||
|
int GetSampleRate( int rate ) const;
|
||||||
|
|
||||||
void Update(float delta);
|
void Update(float delta);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class RageSound_OSS: public RageSoundDriver
|
|||||||
public:
|
public:
|
||||||
bool GetData();
|
bool GetData();
|
||||||
void Update(float delta);
|
void Update(float delta);
|
||||||
int GetSampleRate() const { return samplerate; }
|
int GetSampleRate( int rate ) const { return samplerate; }
|
||||||
|
|
||||||
/* virtuals: */
|
/* virtuals: */
|
||||||
void StartMixing(RageSound *snd); /* used by RageSound */
|
void StartMixing(RageSound *snd); /* used by RageSound */
|
||||||
|
|||||||
Reference in New Issue
Block a user