From 69cf82de491b0c9d2201efa290db3fd55324ca77 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Sat, 24 Jul 2004 02:01:12 +0000 Subject: [PATCH] handle mono --- stepmania/src/RageSound.cpp | 29 ++++++++++++++++-- stepmania/src/RageSoundReader_Vorbisfile.cpp | 32 ++++++++------------ stepmania/src/RageSoundReader_Vorbisfile.h | 2 ++ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index ff5896dd3d..fa668943bf 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -281,7 +281,7 @@ void RageSound::RateChange(char *buf, int &cnt, /* Fill the buffer by about "bytes" worth of data. (We might go a little * over, and we won't overflow our buffer.) Return the number of bytes - * actually read; 0 = EOF. */ + * actually read; 0 = EOF. Convert mono input to stereo. */ int RageSound::FillBuf( int frames ) { ASSERT(Sample); @@ -295,7 +295,6 @@ int RageSound::FillBuf( int frames ) char inbuf[10240]; unsigned read_size = read_block_size; - int cnt = 0; if( m_Param.speed_input_samples != m_Param.speed_output_samples ) { @@ -309,12 +308,36 @@ int RageSound::FillBuf( int frames ) ASSERT(read_size < sizeof(inbuf)); } + /* channels == 2; we want stereo. If the input data is mono, read half as many + * samples. */ + if( Sample->GetNumChannels() == 1 ) + read_size /= 2; + ASSERT(read_size < sizeof(inbuf)); - cnt = Sample->Read(inbuf, read_size); + int cnt = Sample->Read(inbuf, read_size); if(cnt == 0) return got_something; /* EOF */ + if( Sample->GetNumChannels() == 1 ) + { + /* Dupe mono to stereo in-place; do it in reverse, to handle overlap. */ + int num_samples = cnt / sizeof(int16_t); + float *input = (float *) inbuf; + float *output = input; + input += num_samples; + output += num_samples*2; + while( num_samples-- ) + { + input -= 1; + output -= 2; + output[0] = input[0]; + output[1] = input[0]; + } + + cnt *= 2; + } + if(cnt == -1) { Fail(Sample->GetError()); diff --git a/stepmania/src/RageSoundReader_Vorbisfile.cpp b/stepmania/src/RageSoundReader_Vorbisfile.cpp index 25541d2193..eb5f6a12c0 100644 --- a/stepmania/src/RageSoundReader_Vorbisfile.cpp +++ b/stepmania/src/RageSoundReader_Vorbisfile.cpp @@ -54,8 +54,6 @@ static long OggRageFile_tell_func( void *datasource ) return f->Tell(); } -const int channels = 2; - const int read_block_size = 1024; @@ -131,6 +129,10 @@ SoundReader_FileReader::OpenResult RageSoundReader_Vorbisfile::Open(CString file eof = false; read_offset = (int) ov_pcm_tell(vf); + vorbis_info *vi = ov_info( vf, -1 ); + ASSERT_M( vi->channels == 1 || vi->channels == 2, ssprintf("%i", vi->channels) ); + channels = vi->channels; + return OPEN_OK; } @@ -183,9 +185,12 @@ bool RageSoundReader_Vorbisfile::FillBuf() vorbis_info *vi = ov_info( vf, -1 ); ASSERT( vi != NULL ); - const int bytes_per_frame = 2*vi->channels; - char tmpbuf[4096]; + if( (unsigned) vi->channels != channels ) + RageException::Throw( "File \"%s\" changes channel count from %i to %i; not supported", channels, vi->channels ); + + const int bytes_per_frame = sizeof(int16_t)*vi->channels; + int ret = 0; { @@ -207,9 +212,9 @@ bool RageSoundReader_Vorbisfile::FillBuf() /* In bytes: */ int silence = (curofs - read_offset) * bytes_per_frame; CHECKPOINT_M( ssprintf("p %i,%i: %i frames of silence needed", curofs, read_offset, silence) ); - silence = min( silence, (int) sizeof(tmpbuf) ); + silence = min( silence, (int) sizeof(buffer) ); - memset( tmpbuf, 0, silence ); + memset( buffer, 0, silence ); ret = silence; } } @@ -218,9 +223,9 @@ bool RageSoundReader_Vorbisfile::FillBuf() { int bstream; #if defined(INTEGER_VORBIS) - ret = ov_read( vf, tmpbuf, sizeof(tmpbuf), &bstream ); + ret = ov_read( vf, buffer, sizeof(buffer), &bstream ); #else // float vorbis decoder - ret = ov_read( vf, tmpbuf, sizeof(tmpbuf), (BYTE_ORDER == BIG_ENDIAN)?1:0, 2, 1, &bstream ); + ret = ov_read( vf, buffer, sizeof(buffer), (BYTE_ORDER == BIG_ENDIAN)?1:0, 2, 1, &bstream ); #endif if( ret == OV_HOLE ) @@ -242,17 +247,6 @@ bool RageSoundReader_Vorbisfile::FillBuf() /* If we have a different number of channels, we need to convert. */ ASSERT( vi->channels == 1 || vi->channels == 2 ); - if( vi->channels == 1 ) - { - int16_t *indata = (int16_t *)tmpbuf; - int16_t *outdata = (int16_t *)buffer; - int size = ret / sizeof(int16_t); - for( unsigned pos = 0; pos < unsigned(size); ++pos ) - outdata[pos*2] = outdata[pos*2+1] = indata[pos]; - ret *= 2; - } - else - memcpy( buffer, tmpbuf, ret ); avail = ret; return true; diff --git a/stepmania/src/RageSoundReader_Vorbisfile.h b/stepmania/src/RageSoundReader_Vorbisfile.h index 0a0da57fb8..6d16573f05 100644 --- a/stepmania/src/RageSoundReader_Vorbisfile.h +++ b/stepmania/src/RageSoundReader_Vorbisfile.h @@ -18,6 +18,7 @@ class RageSoundReader_Vorbisfile: public SoundReader_FileReader { bool FillBuf(); CString filename; int read_offset; + unsigned channels; public: OpenResult Open(CString filename); @@ -27,6 +28,7 @@ public: int SetPosition_Fast(int ms) { return SetPosition(ms, false); } int Read(char *buf, unsigned len); int GetSampleRate() const; + unsigned GetNumChannels() const { return channels; } RageSoundReader_Vorbisfile(); ~RageSoundReader_Vorbisfile(); SoundReader *Copy() const;