Move the linear resampler to RageSoundReader_Resample_Fast.
Add RageSoundReader_Resample_Good, using libresample.
This commit is contained in:
@@ -1,103 +1,23 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "RageSoundReader_Resample.h"
|
#include "RageSoundReader_Resample.h"
|
||||||
|
#include "RageSoundReader_Resample_Fast.h"
|
||||||
|
#include "RageSoundReader_Resample_Good.h"
|
||||||
|
|
||||||
RageSoundReader_Resample::RageSoundReader_Resample()
|
RageSoundReader_Resample *RageSoundReader_Resample::MakeResampler( ResampleQuality q )
|
||||||
{
|
{
|
||||||
source = NULL;
|
switch( q )
|
||||||
samplerate = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RageSoundReader_Resample::Open(SoundReader *source_)
|
|
||||||
{
|
{
|
||||||
source = source_;
|
case RESAMP_FAST:
|
||||||
ASSERT(source);
|
return new RageSoundReader_Resample_Fast;
|
||||||
|
case RESAMP_NORMAL:
|
||||||
samplerate = source->GetSampleRate();
|
case RESAMP_HIGHQUALITY:
|
||||||
resamp.SetInputSampleRate(samplerate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RageSoundReader_Resample::~RageSoundReader_Resample()
|
|
||||||
{
|
{
|
||||||
delete source;
|
RageSoundReader_Resample_Good *ret = new RageSoundReader_Resample_Good;
|
||||||
}
|
ret->SetHighQuality( q == RESAMP_HIGHQUALITY );
|
||||||
|
|
||||||
void RageSoundReader_Resample::SetSampleRate(int hz)
|
|
||||||
{
|
|
||||||
samplerate = hz;
|
|
||||||
resamp.SetOutputSampleRate(samplerate);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RageSoundReader_Resample::GetLength() const
|
|
||||||
{
|
|
||||||
resamp.reset();
|
|
||||||
return source->GetLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
int RageSoundReader_Resample::GetLength_Fast() const
|
|
||||||
{
|
|
||||||
resamp.reset();
|
|
||||||
return source->GetLength_Fast();
|
|
||||||
}
|
|
||||||
|
|
||||||
int RageSoundReader_Resample::SetPosition_Accurate(int ms)
|
|
||||||
{
|
|
||||||
resamp.reset();
|
|
||||||
return source->SetPosition_Accurate(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
int RageSoundReader_Resample::SetPosition_Fast(int ms)
|
|
||||||
{
|
|
||||||
resamp.reset();
|
|
||||||
return source->SetPosition_Fast(ms);
|
|
||||||
}
|
|
||||||
static const int BUFSIZE = 1024*16;
|
|
||||||
|
|
||||||
int RageSoundReader_Resample::Read(char *buf, unsigned len)
|
|
||||||
{
|
|
||||||
int bytes_read = 0;
|
|
||||||
while(len)
|
|
||||||
{
|
|
||||||
int size = resamp.read(buf, len);
|
|
||||||
|
|
||||||
if(size == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
buf += size;
|
|
||||||
len -= size;
|
|
||||||
bytes_read += size;
|
|
||||||
|
|
||||||
if(size == 0)
|
|
||||||
{
|
|
||||||
static char buf[BUFSIZE];
|
|
||||||
|
|
||||||
int cnt = source->Read(buf, sizeof(buf));
|
|
||||||
|
|
||||||
if(cnt == -1)
|
|
||||||
{
|
|
||||||
SetError(source->GetError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(cnt == 0)
|
|
||||||
resamp.eof();
|
|
||||||
else
|
|
||||||
resamp.write(buf, cnt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundReader *RageSoundReader_Resample::Copy() const
|
|
||||||
{
|
|
||||||
SoundReader *new_source = source->Copy();
|
|
||||||
RageSoundReader_Resample *ret = new RageSoundReader_Resample;
|
|
||||||
ret->Open(new_source);
|
|
||||||
ret->SetSampleRate(samplerate);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
/*
|
ASSERT(0);
|
||||||
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
return NULL;
|
||||||
* Glenn Maynard
|
}
|
||||||
*/
|
}
|
||||||
|
|||||||
@@ -7,28 +7,15 @@
|
|||||||
/* This class changes the sampling rate of a sound. */
|
/* This class changes the sampling rate of a sound. */
|
||||||
class RageSoundReader_Resample: public SoundReader
|
class RageSoundReader_Resample: public SoundReader
|
||||||
{
|
{
|
||||||
int samplerate;
|
|
||||||
|
|
||||||
SoundReader *source;
|
|
||||||
|
|
||||||
mutable RageSoundResampler resamp;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* We own source. */
|
/* We own source. */
|
||||||
void Open(SoundReader *source);
|
virtual void Open(SoundReader *source) = 0;
|
||||||
int GetLength() const;
|
|
||||||
int GetLength_Fast() const;
|
|
||||||
int SetPosition_Accurate(int ms);
|
|
||||||
int SetPosition_Fast(int ms);
|
|
||||||
int Read(char *buf, unsigned len);
|
|
||||||
RageSoundReader_Resample();
|
|
||||||
virtual ~RageSoundReader_Resample();
|
|
||||||
SoundReader *Copy() const;
|
|
||||||
|
|
||||||
/* Change the actual sample rate of a sound. */
|
/* Change the actual sample rate of a sound. */
|
||||||
void SetSampleRate(int hz);
|
virtual void SetSampleRate(int hz) = 0;
|
||||||
|
|
||||||
int GetSampleRate() const { return samplerate; }
|
enum ResampleQuality { RESAMP_FAST, RESAMP_NORMAL, RESAMP_HIGHQUALITY };
|
||||||
|
static RageSoundReader_Resample *MakeResampler( ResampleQuality q );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "RageSoundReader_Resample_Fast.h"
|
||||||
|
|
||||||
|
RageSoundReader_Resample_Fast::RageSoundReader_Resample_Fast()
|
||||||
|
{
|
||||||
|
source = NULL;
|
||||||
|
samplerate = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RageSoundReader_Resample_Fast::Open(SoundReader *source_)
|
||||||
|
{
|
||||||
|
source = source_;
|
||||||
|
ASSERT(source);
|
||||||
|
|
||||||
|
samplerate = source->GetSampleRate();
|
||||||
|
resamp.SetInputSampleRate(samplerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RageSoundReader_Resample_Fast::~RageSoundReader_Resample_Fast()
|
||||||
|
{
|
||||||
|
delete source;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RageSoundReader_Resample_Fast::SetSampleRate(int hz)
|
||||||
|
{
|
||||||
|
samplerate = hz;
|
||||||
|
resamp.SetOutputSampleRate(samplerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Fast::GetLength() const
|
||||||
|
{
|
||||||
|
resamp.reset();
|
||||||
|
return source->GetLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Fast::GetLength_Fast() const
|
||||||
|
{
|
||||||
|
resamp.reset();
|
||||||
|
return source->GetLength_Fast();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Fast::SetPosition_Accurate(int ms)
|
||||||
|
{
|
||||||
|
resamp.reset();
|
||||||
|
return source->SetPosition_Accurate(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Fast::SetPosition_Fast(int ms)
|
||||||
|
{
|
||||||
|
resamp.reset();
|
||||||
|
return source->SetPosition_Fast(ms);
|
||||||
|
}
|
||||||
|
static const int BUFSIZE = 1024*16;
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Fast::Read(char *buf, unsigned len)
|
||||||
|
{
|
||||||
|
int bytes_read = 0;
|
||||||
|
while(len)
|
||||||
|
{
|
||||||
|
int size = resamp.read(buf, len);
|
||||||
|
|
||||||
|
if(size == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
buf += size;
|
||||||
|
len -= size;
|
||||||
|
bytes_read += size;
|
||||||
|
|
||||||
|
if(size == 0)
|
||||||
|
{
|
||||||
|
static char buf[BUFSIZE];
|
||||||
|
|
||||||
|
int cnt = source->Read(buf, sizeof(buf));
|
||||||
|
|
||||||
|
if(cnt == -1)
|
||||||
|
{
|
||||||
|
SetError(source->GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(cnt == 0)
|
||||||
|
resamp.eof();
|
||||||
|
else
|
||||||
|
resamp.write(buf, cnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundReader *RageSoundReader_Resample_Fast::Copy() const
|
||||||
|
{
|
||||||
|
SoundReader *new_source = source->Copy();
|
||||||
|
RageSoundReader_Resample_Fast *ret = new RageSoundReader_Resample_Fast;
|
||||||
|
ret->Open(new_source);
|
||||||
|
ret->SetSampleRate(samplerate);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
||||||
|
* Glenn Maynard
|
||||||
|
*/
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef RAGE_SOUND_READER_RESAMPLE_FAST
|
||||||
|
#define RAGE_SOUND_READER_RESAMPLE_FAST
|
||||||
|
|
||||||
|
#include "RageSoundReader.h"
|
||||||
|
#include "RageSoundReader_Resample.h"
|
||||||
|
#include "RageSoundResampler.h"
|
||||||
|
|
||||||
|
/* This class changes the sampling rate of a sound. */
|
||||||
|
class RageSoundReader_Resample_Fast: public RageSoundReader_Resample
|
||||||
|
{
|
||||||
|
int samplerate;
|
||||||
|
|
||||||
|
bool FillBuf();
|
||||||
|
|
||||||
|
SoundReader *source;
|
||||||
|
|
||||||
|
mutable RageSoundResampler resamp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* We own source. */
|
||||||
|
void Open(SoundReader *source);
|
||||||
|
int GetLength() const;
|
||||||
|
int GetLength_Fast() const;
|
||||||
|
int SetPosition_Accurate(int ms);
|
||||||
|
int SetPosition_Fast(int ms);
|
||||||
|
int Read(char *buf, unsigned len);
|
||||||
|
RageSoundReader_Resample_Fast();
|
||||||
|
virtual ~RageSoundReader_Resample_Fast();
|
||||||
|
SoundReader *Copy() const;
|
||||||
|
|
||||||
|
/* Change the actual sample rate of a sound. */
|
||||||
|
void SetSampleRate(int hz);
|
||||||
|
|
||||||
|
int GetSampleRate() const { return samplerate; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
||||||
|
* Glenn Maynard
|
||||||
|
*/
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "RageLog.h"
|
||||||
|
#include "RageUtil.h"
|
||||||
|
#include "RageSoundReader_Resample_Good.h"
|
||||||
|
|
||||||
|
#include "libresample/include/resample.h"
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#pragma comment(lib, "libresample/resample.lib")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "RageTimer.h"
|
||||||
|
|
||||||
|
RageSoundReader_Resample_Good::RageSoundReader_Resample_Good()
|
||||||
|
{
|
||||||
|
resamp[0] = resamp[1] = NULL;
|
||||||
|
source = NULL;
|
||||||
|
samplerate = -1;
|
||||||
|
BufSamples = 0;
|
||||||
|
eof = false;
|
||||||
|
HighQuality = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call this if the input position is changed or reset. */
|
||||||
|
void RageSoundReader_Resample_Good::Reset() const
|
||||||
|
{
|
||||||
|
BufSamples = 0;
|
||||||
|
eof = false;
|
||||||
|
FlushResampler();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Call this if the input position is changed or reset. */
|
||||||
|
void RageSoundReader_Resample_Good::FlushResampler() const
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 2; ++i )
|
||||||
|
{
|
||||||
|
if( resamp[i] )
|
||||||
|
resample_close( resamp[i] );
|
||||||
|
|
||||||
|
resamp[i] = resample_dup( empty_resamp[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Call this if the sample factor changes. */
|
||||||
|
void RageSoundReader_Resample_Good::ReopenResampler() const
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 2; ++i )
|
||||||
|
{
|
||||||
|
if( resamp[i] )
|
||||||
|
resample_close( resamp[i] );
|
||||||
|
|
||||||
|
resamp[i] = resample_open( HighQuality, GetFactor()-0.1f, GetFactor()+0.1f );
|
||||||
|
empty_resamp[i] = resample_dup( resamp[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RageSoundReader_Resample_Good::Open(SoundReader *source_)
|
||||||
|
{
|
||||||
|
source = source_;
|
||||||
|
ASSERT(source);
|
||||||
|
|
||||||
|
samplerate = source->GetSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RageSoundReader_Resample_Good::~RageSoundReader_Resample_Good()
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 2; ++i )
|
||||||
|
{
|
||||||
|
if( resamp[i] )
|
||||||
|
resample_close( resamp[i] );
|
||||||
|
if( empty_resamp[i] )
|
||||||
|
resample_close( empty_resamp[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete source;
|
||||||
|
}
|
||||||
|
|
||||||
|
float RageSoundReader_Resample_Good::GetFactor() const
|
||||||
|
{
|
||||||
|
return float(samplerate) / source->GetSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RageSoundReader_Resample_Good::SetSampleRate(int hz)
|
||||||
|
{
|
||||||
|
samplerate = hz;
|
||||||
|
ReopenResampler();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Good::GetLength() const
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return source->GetLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Good::GetLength_Fast() const
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return source->GetLength_Fast();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Good::SetPosition_Accurate(int ms)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return source->SetPosition_Accurate(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Good::SetPosition_Fast(int ms)
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
return source->SetPosition_Fast(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RageSoundReader_Resample_Good::FillBuf()
|
||||||
|
{
|
||||||
|
int samples_free = BUFSIZE-BufSamples;
|
||||||
|
if( eof )
|
||||||
|
return true;
|
||||||
|
if( !samples_free )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Sint16 tmpbuf[BUFSIZE*2];
|
||||||
|
int cnt = source->Read((char *) tmpbuf, samples_free * sizeof(Sint16) * 2);
|
||||||
|
|
||||||
|
if( cnt == -1 )
|
||||||
|
{
|
||||||
|
SetError(source->GetError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (unsigned) cnt < samples_free * sizeof(Sint16) * 2 )
|
||||||
|
eof = true;
|
||||||
|
|
||||||
|
cnt /= sizeof(Sint16);
|
||||||
|
cnt /= 2;
|
||||||
|
|
||||||
|
for( int c = 0; c < 2; ++c )
|
||||||
|
{
|
||||||
|
for( int s = 0; s < cnt; ++s )
|
||||||
|
inbuf[c][s+BufSamples] = tmpbuf[s*2+c];
|
||||||
|
}
|
||||||
|
BufSamples += cnt;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RageSoundReader_Resample_Good::Read(char *bufp, unsigned len)
|
||||||
|
{
|
||||||
|
Sint16 *buf = (Sint16 *) bufp;
|
||||||
|
len /= 2;
|
||||||
|
const float factor = GetFactor();
|
||||||
|
|
||||||
|
int bytes_read = 0;
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
int samples_used = 0, samples_output = 0;
|
||||||
|
if( BufSamples )
|
||||||
|
{
|
||||||
|
for( int c = 0; c < 2; ++c )
|
||||||
|
{
|
||||||
|
ASSERT( resamp[c] );
|
||||||
|
float outbuf[BUFSIZE];
|
||||||
|
samples_output = resample_process(resamp[c],
|
||||||
|
factor,
|
||||||
|
inbuf[c], BufSamples,
|
||||||
|
eof,
|
||||||
|
&samples_used,
|
||||||
|
outbuf, len/2);
|
||||||
|
if( samples_output == -1 )
|
||||||
|
RageException::Throw( "Unexpected resample_process return value: -1" );
|
||||||
|
|
||||||
|
memmove( inbuf[c], &inbuf[c][samples_used], sizeof(float) * (BufSamples-samples_used) );
|
||||||
|
|
||||||
|
for( int s = 0; s < samples_output; ++s )
|
||||||
|
{
|
||||||
|
buf[s*2+c] = Sint16(clamp(outbuf[s], -32768, 32767));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BufSamples -= samples_used;
|
||||||
|
|
||||||
|
if( !samples_output )
|
||||||
|
{
|
||||||
|
if( !len )
|
||||||
|
return bytes_read; /* buffer full */
|
||||||
|
if( eof )
|
||||||
|
return bytes_read; /* EOF and we're completely flushed */
|
||||||
|
if( !FillBuf() )
|
||||||
|
return -1; /* source error */
|
||||||
|
}
|
||||||
|
|
||||||
|
len -= samples_output*2;
|
||||||
|
buf += samples_output*2;
|
||||||
|
bytes_read += samples_output*2*sizeof(Sint16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundReader *RageSoundReader_Resample_Good::Copy() const
|
||||||
|
{
|
||||||
|
SoundReader *new_source = source->Copy();
|
||||||
|
RageSoundReader_Resample_Good *ret = new RageSoundReader_Resample_Good;
|
||||||
|
|
||||||
|
for( int c = 0; c < 2; ++c )
|
||||||
|
{
|
||||||
|
ASSERT( resamp[c] );
|
||||||
|
ret->resamp[c] = resample_dup( resamp[c] );
|
||||||
|
ret->empty_resamp[c] = resample_dup( empty_resamp[c] );
|
||||||
|
}
|
||||||
|
ret->source = new_source;
|
||||||
|
ret->HighQuality = HighQuality;
|
||||||
|
ret->samplerate = samplerate;
|
||||||
|
memcpy( ret->inbuf, inbuf, sizeof(inbuf));
|
||||||
|
ret->BufSamples = BufSamples;
|
||||||
|
ret->eof = eof;
|
||||||
|
|
||||||
|
// ret->Open(new_source);
|
||||||
|
// ret->SetSampleRate(samplerate);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
||||||
|
* Glenn Maynard
|
||||||
|
*/
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef RAGE_SOUND_READER_RESAMPLE_GOOD
|
||||||
|
#define RAGE_SOUND_READER_RESAMPLE_GOOD
|
||||||
|
|
||||||
|
#include "RageSoundReader.h"
|
||||||
|
#include "RageSoundReader_Resample.h"
|
||||||
|
|
||||||
|
/* This class changes the sampling rate of a sound. */
|
||||||
|
class RageSoundReader_Resample_Good: public RageSoundReader_Resample
|
||||||
|
{
|
||||||
|
enum { BUFSIZE = 4096 };
|
||||||
|
|
||||||
|
SoundReader *source;
|
||||||
|
bool HighQuality;
|
||||||
|
int samplerate;
|
||||||
|
|
||||||
|
/* Mutable hell, since GetLength pretends to be const but isn't yet. */
|
||||||
|
mutable void *resamp[2];
|
||||||
|
mutable void *empty_resamp[2];
|
||||||
|
float inbuf[2][BUFSIZE];
|
||||||
|
mutable int BufSamples;
|
||||||
|
mutable bool eof;
|
||||||
|
|
||||||
|
void Reset() const;
|
||||||
|
void FlushResampler() const;
|
||||||
|
void ReopenResampler() const;
|
||||||
|
float GetFactor() const;
|
||||||
|
bool FillBuf();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* We own source. */
|
||||||
|
void Open(SoundReader *source);
|
||||||
|
int GetLength() const;
|
||||||
|
int GetLength_Fast() const;
|
||||||
|
int SetPosition_Accurate(int ms);
|
||||||
|
int SetPosition_Fast(int ms);
|
||||||
|
int Read(char *buf, unsigned len);
|
||||||
|
RageSoundReader_Resample_Good();
|
||||||
|
virtual ~RageSoundReader_Resample_Good();
|
||||||
|
SoundReader *Copy() const;
|
||||||
|
|
||||||
|
/* Change the actual sample rate of a sound. */
|
||||||
|
void SetSampleRate( int hz );
|
||||||
|
void SetHighQuality( bool hq ) { HighQuality = hq; }
|
||||||
|
|
||||||
|
int GetSampleRate() const { return samplerate; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2003 by the person(s) listed below. All rights reserved.
|
||||||
|
* Glenn Maynard
|
||||||
|
*/
|
||||||
Reference in New Issue
Block a user