mirror of https://github.com/stella-emu/stella.git
implemented gapless playback for WAV files (KidVid)
This commit is contained in:
parent
9d6cee710e
commit
a647b2ba7f
|
@ -401,39 +401,44 @@ void SoundSDL2::callback(void* udata, uInt8* stream, int len)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL2::playWav(const string& fileName, uInt32 position, uInt32 length)
|
||||
bool SoundSDL2::playWav(const string& fileName, const uInt32 position,
|
||||
const uInt32 length)
|
||||
{
|
||||
uInt32 wavLength{0};
|
||||
|
||||
// Stop any playing WAVs
|
||||
stopWav();
|
||||
|
||||
// Load WAV file
|
||||
auto* result = SDL_LoadWAV(fileName.c_str(), &myWavSpec, &myWavBuffer, &wavLength);
|
||||
if(result == nullptr || position > wavLength)
|
||||
if(fileName != myWavFilename || myWavBuffer == nullptr)
|
||||
{
|
||||
if(myWavBuffer)
|
||||
{
|
||||
SDL_FreeWAV(myWavBuffer);
|
||||
myWavBuffer = nullptr;
|
||||
}
|
||||
if(SDL_LoadWAV(fileName.c_str(), &myWavSpec, &myWavBuffer, &myWavLength) == nullptr)
|
||||
return false;
|
||||
// Set the callback function
|
||||
myWavSpec.callback = wavCallback;
|
||||
myWavSpec.userdata = nullptr;
|
||||
}
|
||||
if(position > myWavLength)
|
||||
return false;
|
||||
|
||||
length = length
|
||||
? std::min(length, wavLength - position)
|
||||
: wavLength;
|
||||
|
||||
// Set the callback function
|
||||
myWavSpec.callback = wavCallback;
|
||||
myWavSpec.userdata = nullptr;
|
||||
myWavFilename = fileName;
|
||||
|
||||
myWavLen = length
|
||||
? std::min(length, myWavLength - position)
|
||||
: myWavLength;
|
||||
myWavPos = myWavBuffer + position;
|
||||
myWavLen = length;
|
||||
|
||||
// Open audio device
|
||||
const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr;
|
||||
|
||||
myWavDevice = SDL_OpenAudioDevice(device, 0, &myWavSpec, nullptr, 0);
|
||||
if(!myWavDevice)
|
||||
return false;
|
||||
|
||||
// Play audio
|
||||
SDL_PauseAudioDevice(myWavDevice, 0);
|
||||
{
|
||||
const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr;
|
||||
|
||||
myWavDevice = SDL_OpenAudioDevice(device, 0, &myWavSpec, nullptr, 0);
|
||||
if(!myWavDevice)
|
||||
return false;
|
||||
// Play audio
|
||||
SDL_PauseAudioDevice(myWavDevice, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -443,9 +448,10 @@ void SoundSDL2::stopWav()
|
|||
if(myWavBuffer)
|
||||
{
|
||||
// Clean up
|
||||
myWavLen = 0;
|
||||
SDL_CloseAudioDevice(myWavDevice);
|
||||
myWavDevice = 0;
|
||||
SDL_FreeWAV(myWavBuffer);
|
||||
|
||||
myWavBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,8 +116,8 @@ class SoundSDL2 : public Sound
|
|||
|
||||
@return True, if the WAV file can be played
|
||||
*/
|
||||
bool playWav(const string& fileName, uInt32 position = 0,
|
||||
uInt32 length = 0) override;
|
||||
bool playWav(const string& fileName, const uInt32 position = 0,
|
||||
const uInt32 length = 0) override;
|
||||
|
||||
/**
|
||||
Stop any currently playing WAV file.
|
||||
|
@ -186,6 +186,8 @@ class SoundSDL2 : public Sound
|
|||
AudioSettings& myAudioSettings;
|
||||
|
||||
// WAV file sound variables
|
||||
string myWavFilename{EmptyString};
|
||||
uInt32 myWavLength{0};
|
||||
SDL_AudioDeviceID myWavDevice{0};
|
||||
uInt8* myWavBuffer{nullptr};
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ void KidVid::update()
|
|||
{
|
||||
// Continue playing song after state load
|
||||
const uInt8 temp = ourSongPositions[mySongPointer - 1] & 0x7f;
|
||||
const uInt32 songLength = ourSongStart[temp + 1] - ourSongStart[temp];
|
||||
const uInt32 songLength = ourSongStart[temp + 1] - ourSongStart[temp] - (262 * ClickFrames);
|
||||
|
||||
// Play the remaining WAV file
|
||||
const string& fileName = myOSystem.baseDir().getPath() + ((temp < 10) ? "KVSHARED.WAV" : getFileName());
|
||||
|
@ -140,6 +140,10 @@ void KidVid::update()
|
|||
{
|
||||
setPin(DigitalPin::Four, (ourData[myIdx >> 3] << (myIdx & 0x07)) & 0x80);
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
cerr << (DigitalPin::Four, (ourData[myIdx >> 3] << (myIdx & 0x07)) & 0x80 ? "X" : ".");
|
||||
#endif
|
||||
|
||||
// increase to next bit
|
||||
++myIdx;
|
||||
--myBlockIdx;
|
||||
|
@ -172,7 +176,7 @@ void KidVid::update()
|
|||
if(mySongPlaying)
|
||||
{
|
||||
mySongLength = myOSystem.sound().wavSize();
|
||||
myTapeBusy = (mySongLength > 262 * ClickFrames) || !myBeep;
|
||||
myTapeBusy = (mySongLength > 262 * TapeFrames) || !myBeep;
|
||||
// Check for end of played sample
|
||||
if(mySongLength == 0)
|
||||
{
|
||||
|
@ -188,7 +192,7 @@ void KidVid::update()
|
|||
if(mySongLength)
|
||||
{
|
||||
--mySongLength;
|
||||
myTapeBusy = (mySongLength > ClickFrames);
|
||||
myTapeBusy = (mySongLength > TapeFrames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -259,6 +263,7 @@ void KidVid::openSampleFiles()
|
|||
44 + 38 + 42 + 62
|
||||
};
|
||||
|
||||
#ifdef SOUND_SUPPORT
|
||||
if(!myFilesFound)
|
||||
{
|
||||
int i = myGame == Game::Smurfs ? myTape - 1 : myTape + 2;
|
||||
|
@ -267,13 +272,14 @@ void KidVid::openSampleFiles()
|
|||
myFilesFound = FSNode(myOSystem.baseDir().getPath() + getFileName()).exists() &&
|
||||
FSNode(myOSystem.baseDir().getPath() + "KVSHARED.WAV").exists();
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
#ifdef DEBUG_BUILD
|
||||
if(myFilesFound)
|
||||
cerr << endl
|
||||
<< "found file: " << getFileName() << endl
|
||||
<< "found file: " << "KVSHARED.WAV" << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
mySongLength = 0;
|
||||
mySongPointer = firstSongPointer[i];
|
||||
}
|
||||
|
@ -288,7 +294,7 @@ void KidVid::setNextSong()
|
|||
myBeep = (ourSongPositions[mySongPointer] & 0x80) == 0;
|
||||
|
||||
const uInt8 temp = ourSongPositions[mySongPointer] & 0x7f;
|
||||
mySongLength = ourSongStart[temp + 1] - ourSongStart[temp];
|
||||
mySongLength = ourSongStart[temp + 1] - ourSongStart[temp] - (262 * ClickFrames);
|
||||
|
||||
// Play the WAV file
|
||||
const string& fileName = (temp < 10) ? "KVSHARED.WAV" : getFileName();
|
||||
|
@ -298,9 +304,9 @@ void KidVid::setNextSong()
|
|||
msg << "Read song #" << mySongPointer << " (" << fileName << ")";
|
||||
myCallback(msg.str(), false);
|
||||
|
||||
#ifdef DEBUG_BUILD
|
||||
#ifdef DEBUG_BUILD
|
||||
cerr << fileName << ": " << (ourSongPositions[mySongPointer] & 0x7f) << endl;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
mySongPlaying = myTapeBusy = true;
|
||||
++mySongPointer;
|
||||
|
@ -309,7 +315,7 @@ void KidVid::setNextSong()
|
|||
{
|
||||
myBeep = true;
|
||||
myTapeBusy = true;
|
||||
mySongLength = 80; /* delay needed for Harmony without tape */
|
||||
mySongLength = TapeFrames + 32; /* delay needed for Harmony without tape */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,14 +444,14 @@ const std::array<uInt32, KidVid::SongStartSize> KidVid::ourSongStart = {
|
|||
3059116,
|
||||
|
||||
/* kvs1 */
|
||||
44, /* Harmony into 1 */
|
||||
164685, /* falling notes (into 2) */
|
||||
44, /* Harmony intro 1 */
|
||||
164685, /* falling notes (intro 2) */
|
||||
395182, /* instructions */
|
||||
750335, /* high notes are high */
|
||||
962016, /* my hat's off to you */
|
||||
1204273, /* 1 2 3 do re mi */
|
||||
1538258, /* Harmony */
|
||||
1801683, /* concratulations (all of the Smurfs voted) */
|
||||
1801683, /* congratulations (all of the Smurfs voted) */
|
||||
2086276, /* line or space */
|
||||
2399093, /* hooray */
|
||||
2589606, /* hear yeeh */
|
||||
|
|
|
@ -111,7 +111,8 @@ class KidVid : public Controller
|
|||
NumBlockBits = NumBlocks * 8, // number of bits / block
|
||||
SongPosSize = 44 + 38 + 42 + 62 + 80 + 62,
|
||||
SongStartSize = 104,
|
||||
ClickFrames = 48 // eliminate click noise at song end
|
||||
TapeFrames = 60,
|
||||
ClickFrames = 3 // eliminate click noise at song end
|
||||
;
|
||||
|
||||
// Whether the KidVid device is enabled (only for games that it
|
||||
|
|
|
@ -114,8 +114,8 @@ class Sound
|
|||
|
||||
@return True, if the WAV file can be played
|
||||
*/
|
||||
virtual bool playWav(const string& fileName, uInt32 position = 0,
|
||||
uInt32 length = 0) { return false; }
|
||||
virtual bool playWav(const string& fileName, const uInt32 position = 0,
|
||||
const uInt32 length = 0) { return false; }
|
||||
|
||||
/**
|
||||
Stop any currently playing WAV file.
|
||||
|
|
Loading…
Reference in New Issue