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:
Glenn Maynard
2004-01-03 02:35:47 +00:00
parent 47d4d0ce13
commit a27620a32d
8 changed files with 48 additions and 21 deletions
+20 -9
View File
@@ -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 );
} }
+3 -4
View File
@@ -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();
+1 -1
View File
@@ -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 */