Files
itgmania212121/stepmania/src/RageSound.h
T

170 lines
5.7 KiB
C++
Raw Normal View History

2002-12-13 07:44:34 +00:00
#ifndef RAGE_SOUND_OBJ_H
#define RAGE_SOUND_OBJ_H
#include <deque>
#include "RageTimer.h"
2004-01-14 09:38:14 +00:00
#include "RageUtil_CircularBuffer.h"
2002-12-13 07:44:34 +00:00
2002-12-27 23:15:39 +00:00
class SoundReader;
2004-01-15 02:28:58 +00:00
/* Driver interface for sounds: this is what drivers see. */
2004-01-15 02:31:09 +00:00
class RageSoundBase
2004-01-15 02:28:58 +00:00
{
public:
2004-01-15 02:31:09 +00:00
virtual ~RageSoundBase() { }
2004-01-15 02:28:58 +00:00
virtual void StopPlaying() = 0;
virtual int GetPCM( char *buffer, int size, int sampleno ) = 0;
virtual int GetSampleRate() const = 0;
virtual RageTimer GetStartTime() const { return RageZeroTimer; }
virtual CString GetLoadedFilePath() const = 0;
};
2004-01-15 02:31:09 +00:00
class RageSound: public RageSoundBase
2002-12-13 07:44:34 +00:00
{
2002-12-27 23:15:39 +00:00
public:
/* M_STOP (default) stops the sound after m_LengthSamples have been played.
* M_LOOP restarts from m_StartSample.
* M_CONTINUE feeds silence, which is useful to continue timing longer than the
* actual sound. */
enum StopMode_t {
M_STOP, M_LOOP, M_CONTINUE
} StopMode;
RageSound();
~RageSound();
RageSound(const RageSound &cpy);
2003-01-21 02:44:35 +00:00
/* If cache == true (1), we'll preload the entire file into memory if
* it's small enough. If this is done, a large number of copies of the
* sound can be played without much performance penalty. This is useful
2004-01-14 09:38:14 +00:00
* for BM (keyed sounds), and for rapidly-repeating sound effects, such
2003-01-21 02:44:35 +00:00
* as the music wheel.
*
* If cache == false (0), we'll never preload the file (always stream
* it). This makes loads much faster.
*
* If cache is 2 (the default), it means "don't care". Currently, this
* means false; this may become a preference.
2002-12-27 23:15:39 +00:00
*
* If the file failed to load, false is returned, Error() is set
* and a null sample will be loaded. (This makes failed loads nonfatal;
* they can be ignored most of the time, so we continue to work if a file
* is broken or missing.) */
2003-01-21 02:44:35 +00:00
bool Load(CString fn, int precache = 2);
2002-12-27 23:15:39 +00:00
void Unload();
void SetStopMode(StopMode_t m) { StopMode = m; }
StopMode_t GetStopMode() const { return StopMode; }
void SetStartSeconds(float secs = 0); /* default = beginning */
void SetLengthSeconds(float secs = -1); /* default = no length limit */
void StartPlaying();
void StopPlaying();
CString GetError() const { return error; }
bool Error() const { return !error.empty(); }
RageSound *Play();
void Stop();
float GetLengthSeconds();
2004-01-18 04:01:52 +00:00
float GetPositionSeconds( bool *approximate=NULL, RageTimer *Timestamp=NULL ) const;
2003-04-24 23:51:05 +00:00
int GetSampleRate() const;
2002-12-27 23:15:39 +00:00
bool SetPositionSeconds( float fSeconds = -1);
void SetAccurateSync(bool yes=true) { AccurateSync = yes; }
void SetPlaybackRate( float fScale );
2003-02-10 21:43:50 +00:00
void SetFadeLength( float fSeconds );
void SetNoFade() { SetFadeLength(0); }
2003-01-02 06:52:39 +00:00
float GetPlaybackRate() const { return float(speed_input_samples) / speed_output_samples; }
2002-12-27 23:15:39 +00:00
bool IsPlaying() const { return playing; }
CString GetLoadedFilePath() const { return m_sFilePath; }
void SetStartTime( const RageTimer &tm ) { StartTime = tm; }
RageTimer GetStartTime() const { return StartTime; }
2002-12-27 23:15:39 +00:00
private:
2002-12-22 08:13:33 +00:00
/* If we were copied from another RageSound, this will point to it; otherwise
* this is ourself. */
RageSound *original;
SoundReader *Sample;
2004-01-14 09:38:14 +00:00
CircBuf<char> databuf;
2002-12-27 23:15:39 +00:00
int FillBuf(int bytes);
2002-12-13 07:44:34 +00:00
/* Sound blocks we've sent out recently through GetPCM. We keep track
* of each block for the last four calls of GetPCM. */
struct pos_map_t {
/* Sample number from the POV of the sound driver: */
int sampleno;
/* Actual sound position within the sample: */
int position;
/* The number of samples in this block: */
int samples;
pos_map_t(int samp, int pos, int cnt) { sampleno=samp, position=pos; samples=cnt; }
};
deque<pos_map_t> pos_map;
2004-01-18 02:07:58 +00:00
static int SearchPosMap( const deque<pos_map_t> &pos_map, int cur_sample, bool *approximate );
2004-01-19 20:37:14 +00:00
static void CleanPosMap( deque<pos_map_t> &pos_map );
2004-01-18 02:07:58 +00:00
2002-12-13 07:44:34 +00:00
CString m_sFilePath;
2002-12-18 06:44:56 +00:00
/* The amount of data to play (or loop): */
2002-12-20 02:00:43 +00:00
int m_StartSample, m_LengthSamples;
2002-12-27 23:15:39 +00:00
2002-12-13 07:44:34 +00:00
/* Current position of the output sound; if < 0, nothing will play until it
* becomes positive. This is recorded in samples, to avoid rounding error. */
int position;
2003-01-25 09:01:42 +00:00
2003-02-10 21:43:50 +00:00
/* Amount of time to fade out at the end. */
float fade_length;
2003-01-25 09:01:42 +00:00
/* Hack: When we stop a playing sound, we can't ask the driver the position
* (we're not playing); and we can't seek back to the current playing position
* when we stop (too slow), but we want to be able to report the position we
* were at when we stopped without jumping to the last position we buffered. */
2003-10-03 09:00:02 +00:00
int stopped_position;
2002-12-13 07:44:34 +00:00
bool playing;
2003-01-02 06:52:39 +00:00
/* Number of samples input and output when changing speed. Currently,
* this is either 1/1, 5/4 or 4/5. */
int speed_input_samples, speed_output_samples;
2002-12-19 04:08:38 +00:00
bool AccurateSync;
/* Optional driver feature: time to actually start playing sounds. If zero, or if not
* supported, it'll start immediately. */
RageTimer StartTime;
2002-12-27 23:15:39 +00:00
CString error;
2002-12-18 06:44:56 +00:00
int GetPositionSecondsInternal( bool *approximate=NULL ) const;
2002-12-27 23:15:39 +00:00
bool SetPositionSamples( int samples = -1 );
int GetData(char *buffer, int size);
void Fail(CString reason);
int Bytes_Available() const;
2002-12-22 08:13:33 +00:00
2003-01-02 06:52:39 +00:00
static void RateChange(char *buf, int &cnt,
int speed_input_samples, int speed_output_samples, int channels);
2002-12-13 07:44:34 +00:00
public:
2002-12-22 08:13:33 +00:00
/* Used by RageSoundManager: */
RageSound *GetOriginal() { return original; }
2002-12-20 01:45:41 +00:00
/* Called only by the sound drivers: */
/* This function should return the number of bytes actually put into buffer.
* If less than size is returned, it signals the stream to stop; once it's
* flushed, SoundStopped will be called. Until then, SOUNDMAN->GetPosition
* can still be called (the sound is still playing). */
int GetPCM(char *buffer, int size, int sampleno);
void Update(float delta);
2002-12-13 07:44:34 +00:00
};
#endif
2003-03-15 23:27:34 +00:00
/*
-----------------------------------------------------------------------------
Copyright (c) 2002-2003 by the person(s) listed below. All rights reserved.
Glenn Maynard
-----------------------------------------------------------------------------
*/