New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DIRECTOR: add support for absolute timing CD audio playback via cuesheets #5428
Conversation
3fddb3b
to
4b49942
Compare
But you can just add a stub for this in backends/audiocd/win32/win32-audiocd.cpp, like you did for Linux and MacOS, right? |
Just in one of the programs I looked at, there was an example with a multitrack image with multiple files in each of them. I have no prediction if we meet such a beast in the wild. |
As in, one cue with multiple files? That should be fine, though we'll want to make sure that the timing value we're parsing out is consistent between both kinds.
Yeah, definitely. I'll add that now while I wait to figure out a real implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your work.
I have several minor notes, but the most significant one, is that if I read the code correctly, on Linux and Windows, the cue sheets will not be used, because (a) they override the default method and (b) return false
.
So, if I read the code correctly, I would drop those overrides in all backends and at this moment, have playAbsolute()
work only with the CUE sheets, not talking to the real hardware, e.g. leave only the default implementation.
backends/audiocd/sdl/sdl-audiocd.cpp
Outdated
@@ -123,6 +123,12 @@ bool SdlAudioCDManager::play(int track, int numLoops, int startFrame, int durati | |||
return true; | |||
} | |||
|
|||
bool SdlAudioCDManager::playAbsolute(int startFrame, int numLoops, int duration, bool onlyEmulate, | |||
Audio::Mixer::SoundType soundType) { | |||
// TODO not implemented |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused with these. To me, it seems that they will override the default method, e.g. emulation, and will be no-op. Am I reading the code correctly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd gotten confused by the inheritance in a previous iteration and didn't realize I could safely omit playAbsolute
implementations. I've deleted these now.
I checked the SDL docs and see how I think I could implement this method for real, but I also don't have access to a Linux machine to test.
@@ -249,17 +249,19 @@ void CueSheet::parseFilesContext(const char *line) { | |||
int trackNum = atoi(nexttok(s, &s).c_str()); | |||
String trackType = nexttok(s, &s); | |||
|
|||
if (trackNum < 0 || (_currentTrack > 0 && _currentTrack + 1 != trackNum)) { | |||
if (trackNum < 0 || (_currentTrack > 0 && _currentTrack + 2 != trackNum)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is + 2
? Please add a comment above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment explaining it.
|
||
// Not found within any tracks, but could be in the final track | ||
if (frame > _tracks.back().indices.back()) { | ||
debug(5, "CueSheet::getTrackAtFrame: Returning final track"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would turn it into a warning()
, e.g. the user code is requesting us to do something odd, beyond the CD limits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The request isn't as odd as it sounds - I'll update the comment to explain why.
The cuesheet gives us the starting indices of each track, but not track length or ending indices. In other words, we don't know how long the song is - we actually don't have an indication of whether the index the caller passed is in the disc or not, we just know that it comes after the start of this track.
The only actual way to 100% for sure know the number of sectors in the track is to actually check the file on disk and see how large it is. (Or load it as an audio file and check the duration.) That's a bit too complex to handle here; I'd rather defer complexity around loading and examining audio files to the CD audio player.
@@ -22,11 +22,20 @@ | |||
#ifndef DIRECTOR_LINGO_XLIBS_APPLECDXOBJ_H | |||
#define DIRECTOR_LINGO_XLIBS_APPLECDXOBJ_H | |||
|
|||
#include "common/formats/cue.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend forward declaration for Common::CueSheet
instead of the whole #include it in the header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
64cabae
to
a311459
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! There is only a tiny nitpick in regards of code formatting
a311459
to
a9da715
Compare
a9da715
to
65d66ed
Compare
Thank you! |
This adds support for playing CD audio via absolute timecodes instead of via track numbers. This is needed for several Director games. In order for this to work via CD audio emulation, we need access to a full table of contents for the disc. We can't just use the audio files for the CD tracks, because in almost every case, a data track comes before the first CD track - it's impossible to know what absolute sector an audio track begins and ends that without knowing the size of the data track.
To fix this, I've made use of cuesheets in order to have access to a full table of contents of the disc. In absolute playback mode, we check to see if the game directory has a file named
disc.cue
, and if so, we parse that and use it as the TOC. I'm using the new cuesheet parser that @sev- wrote. It's been updated with a few changes to accommodate this:Common::CueSheet
to allow retrieving tracks.The generic emulation-based CD audio player has been updated with a new
playAbsolute
method which takes an absolute timecode as its argument. At the moment, the macOS CD code doesn't implementplayAbsolute
; it's effectively a form of emulation already, which reads the AIFF files that macOS exposes instead of lower-level CDDA playback methods, and so we don't have access to the disc's TOC.I've tested with Classical Cats for Mac. Results so far: it works great, and is playing back music as expected. There is a quirk where it's always playing from frame 0, but that's not the fault of the xlib - I haven't checked where the number is coming from, but it seems to be assigned in lingo outside the xlib.
Marking as draft because I haven't yet implemented true absolute playback support for the Windows or SDL CD-ROM devices. Also marking as a draft for feedback from @sev- on the changes to the cuesheet code.