Extracting score informations in a played soundtrack

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
jseb
Prole
Posts: 3
Joined: Mon Jul 08, 2013 6:13 pm
Location: sat on a chair

Extracting score informations in a played soundtrack

Post by jseb »

Hello,

I use soundtracked music.

The structure of those files (.xm, .mod, .it ...) is interesting for synchronizing events in a game.

That is, as it's basically a score interpreted with embedded sampled instruments, you can extract a lot of informations during the play.
(when you have access to the score)

I'd like to obtain real-time informations about notes currently played and instruments, and so on (effects applied , etc.)


With Lua API, for getting the position currently played on a source, you call:
Source:tell(optional unit)

It returns a number exprimed in the «unit» given as parameter while the call.
By default, «unit» is seconds.

I'd like to modify «tell» function member for tracked music, for getting more than the position in the stream.

«tell» is defined in the Lua wrapper : modules/audio/wrap_Source.cpp
Like this: { "tell", w_Source_tell }

Here is the matching function:

Code: Select all

int w_Source_tell(lua_State *L)
{
        Source *t = luax_checksource(L, 1);
        const char *unit = luaL_optstring(L, 2, "seconds");
        Source::Unit u;
        t->getConstant(unit, u);
        lua_pushnumber(L, t->tell(u));
        return 1;
}
«tell» is of course defined in the class «Source»: modules/audio/Source.cpp
«tell» is a virtual function, not implemented in «Source» class:
virtual float tell(Unit unit) = 0;

We find the member's code in the implementation of the «Source» class ; in the audio external API (OpenAL):

Code: Select all

float Source::tell(Source::Unit unit)
{
  return pool->tell(this, &unit);
}
Let's see the «Pool» class ...

Code: Select all

float Pool::tell(Source *source, void *unit)
{
  thread::Lock lock(mutex);
  return source->tellAtomic(unit);
}
And finally (in Source class again):

Code: Select all

float Source::tellAtomic(void *unit) const
{
  if (valid)
  {
    float offset;
    switch (*((Source::Unit *) unit))
    {
      case Source::UNIT_SAMPLES:
        alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
        if (type == TYPE_STREAM) offset += offsetSamples;
        break;
      case Source::UNIT_SECONDS:
      default:
        alGetSourcef(source, AL_SAMPLE_OFFSET, &offset);
        ALint buffer;
        alGetSourcei(source, AL_BUFFER, &buffer);
        int freq;
        alGetBufferi(buffer, AL_FREQUENCY, &freq);
        offset /= freq;
        if (type == TYPE_STREAM) offset += offsetSeconds;
        break;
    }
    return offset;
  }
  return 0.0f;
}
Huho we're too deep here. We're already playing a sound, and it's too late for getting meta-informations of the tracked music (that is, getting score position, notes played , instruments number in play, and so on).

If someone has an idea, it will be very welcome.
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: Extracting score informations in a played soundtrack

Post by raidho36 »

Implement a function that upon music loading queries it for metadata, and then sends it to Lua as a table when requested? Really though, you would probably need way more control over your tracker music than just setting playing position., you'd need to mute/unmute, set bpm, etc.
jseb
Prole
Posts: 3
Joined: Mon Jul 08, 2013 6:13 pm
Location: sat on a chair

Re: Extracting score informations in a played soundtrack

Post by jseb »

Querying for file metadata at loading won't help.
I could extract the score part of the file quite easily, and put in in a Lua table.

The problem is to know the location in the score while playing.
Love functions work on a sound stream, that is, the file is already decoded. At this stage, it's too late for extracting the informations i want.

So i need to go low-level and doing something like overloading «tell» function for soundtracked files.

The ideal case would be having access to the following modplug functions:

int ModPlug_GetCurrentSpeed(ModPlugFile* file);
int ModPlug_GetCurrentTempo(ModPlugFile* file);
int ModPlug_GetCurrentOrder(ModPlugFile* file);
int ModPlug_GetCurrentPattern(ModPlugFile* file);
int ModPlug_GetCurrentRow(ModPlugFile* file);
int ModPlug_GetPlayingChannels(ModPlugFile* file);

(modplug is the library used by Löve for decoding sountracked files)
I don't know how to do that with Löve.

Thank you for reading.
User avatar
Boolsheet
Inner party member
Posts: 780
Joined: Wed Dec 29, 2010 4:57 am
Location: Switzerland

Re: Extracting score informations in a played soundtrack

Post by Boolsheet »

As you noticed, LÖVE doesn't expose the interface or give any more information. That means it's up to you to load a Lua module for this specific task or modify LÖVE (which is probably a bit tedious because of the Decoder and Source abstractions).

If you use Linux and LuaJIT, maybe its FFI can load a library with those functions so you can stay in Lua and don't have to write C or C++.
Shallow indentations.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 5 guests