Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: Jim on April 06, 2007

Title: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on April 06, 2007
gm.dls is the Windows midi patch bank, it's 3.28Mb long and it's got a few hundred samples in it that might be useful for tiny trackers.
I reversed the format by hand - the file is just a RIFF with blocks for waves and waveheaders.
In fact, though, the format's no secret and it's documented at the midi organisation's own website http://www.midi.org/about-midi/dls/abtdls.shtml (http://www.midi.org/about-midi/dls/abtdls.shtml)

The attached sample code and exe will play back all the samples in the bank.

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: va!n on April 06, 2007
the exe does not works on my XP system.... windows dont like to run the exe
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on April 06, 2007
You're missing msvcrt8.dll.  My mistake, I should have built it static.  I'll update the zip.  Why, oh why, did Microsoft change the message from the useful 'can't find msvcrt8.dll' to the utterly useless 'some component is missing'?

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: benny! on April 06, 2007
Quote from: Jim on April 06, 2007
gm.dls is the Windows midi patch bank, it's 3.28Mb long and it's got a few hundred samples
in it that might be useful for tiny trackers.

Nice ... didn't know of the existance before to be honest. Could come handy indeed for tiny
trackers.


Quote from: Jim on April 06, 2007
I reversed the format by hand - the file is just a RIFF with blocks for waves and waveheaders.
In fact, though, the format's no secret and it's documented at the midi organisation's own website
http://www.midi.org/about-midi/dls/abtdls.shtml (http://www.midi.org/about-midi/dls/abtdls.shtml)

The attached sample code and exe will play back all the samples in the bank.

Works fine here - will have a look on the code later. Thanks for sharing !!!
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Paul on April 06, 2007
I'm sorry to say but it doesn't do anything :S

A window opens and closes before i have time to see anything ???

If it helps I'm running windows 2000 sp4(I think)
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on April 06, 2007
The path is hardcoded to use C:\windows\system32\drivers\gm.dls.  If it's not there it'll just exit.  If you're on Win2K I suspect it's not there.

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Shockwave on April 06, 2007
It works here K+
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on April 06, 2007
->benny!  It's an idea Taj came up with (don't know if it was his idea first) and he posted it again the other day in his answer to va!n on 4k coding.  It's too good an idea to go by the wayside so I thought I'd code it up.

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: benny! on April 06, 2007
@Jim:
Yup. Really interesting. I will have a closer look to the quality of the instruments
in the dll when I have some time ...

And btw. K++ for sharing code (and for testing the "other thing")
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on April 16, 2007
Jim,

thanks for sharing this. Somethings wrong though. I'm using xp, sp2, gm.dls where it should be, but the exe plays maybe 20 samples then no more...it continues to run seemingly forever but the sonud just crackles out.

I was unable to build code using VC++ express  here so I cant switch on debug and give you info. Sorry not much more help.

One suggestion for tiny trackers using this technique...you could make the code smaller by doing this:
1. Writing a parser to find the wav data and output start of data and length for each sample into say a .h file in a structure.

// Uncomment the instruments you want...         
// each samples entry :  address , size
// each samples entry :  address , size
#ifndef __GM_H__

#define __GM_H__

typedef struct wsegmentstruct {
unsigned int address;             // address in gm.dls of this sample
unsigned int length;          // length of this sample
} wsegment;

wsegment GMsamples[]={
//280156,2890, //0
//283212,2848, //1
//286226,12024, //2
//298418,6250, //3
//304836,4820, //4
//309824,15356, //5
//325346,488, //6
//326000,202, //7
//326368,196, //8
//326730,2192, //9
.
.
.
}


then in your 4k code you only need to:
open file
loop:
read sample
create header

which should be (is) tiny.


Chris
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on April 16, 2007
Yeah, it's a bit buggy.  When all the pcm channels are full on the sound card it goes bang.  I fixed it on my own version - waveOutUnprepare() is returning STILL_PLAYING and I'm ignoring it.

The idea was really to show how to parse the file! That bit of it always worked :)

I'm using the same parser to parse some midi files too now, but that's going to need a lot more work.

<edit>I've updated the zip in the original post to fix the bug.  It plays for several minutes.

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: benny! on April 30, 2007
Useful tool related to this topic :

http://www.pouet.net/prod.php?which=30541 (http://www.pouet.net/prod.php?which=30541)
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on April 30, 2007
You have to love blackpawn.
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Rbz on May 02, 2007
Quote from: taj on April 30, 2007
You have to love blackpawn.
Indeed :)

And finally I have created my own routines to extract those samples, blackpawn gave me the last clue I was looking for, because the way that Jim did it  was hard to me to understand  :P

I'm using a header file with samples offset and parser code, something like what you have did Chris  :kewl:

Tiny 4k tracker - here I go!
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on May 02, 2007
Yeah thats very cool rbraz, question is...what sound playback will you use in the end?
I see three options:
1. Copy data from samples into a bi buffer by hanjd, applying envelopes etc as you go.
    The play the whole buffer using playsound.

2. Use MMIO - no ide about this , never used it.

3. Use directsound buffers...this i sthe way I tried, lots of hassle and bugs and then I fonud out you
cant use the FX (my reason for going this way) because you need to use a COM interface which costs bytes!

So any ideas?

Chris
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Rbz on May 02, 2007
Sorry Chris, I'm not sure yet, I'll try first with a buffer and playsound and probably do some tests with directsound too. I don't know anything about MMIO  :(
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on May 02, 2007
waveOut is the technique I used in the ripping code above to play the samples.  It's nice and simple.  Almost everything you need is in that sample, except the synchronisation you might want.

Or there's DirectSound, which I posted a sample of here http://dbfinteractive.com/index.php?topic=1540.0 (http://dbfinteractive.com/index.php?topic=1540.0).
The one whopper I've found in dsound is if you create the primary buffer as a hardware buffer, some drivers will ignore the sample rate you supply and replace it with another one (usually you ask for 44.1KHz and it plays at 48KHz).  This is due to a bug in Microsoft's original dsound driver sample (over 10yrs ago) which everyone just copied!

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on May 03, 2007
Jim,

I tried the directsound route and got it down to about 350 bytes (measured using apack) including loading samples and playing them from their own secondary buffers. I was forced to use a primary buffer in software - was ok. But then found out about the FX requiring COM which annoyed the hell out of me (kb doesnt mention that in his articles probably because he was aiming at 64k where the extra few hundred bytes arent a problem). I also had trouble working out the frequency (never solved it but mayeb I will one day) and getting rid of clicking in the buffers. The source is all in that code I sent out in grodfis2 directory.

In the end I wish I'd tried MMIO instead of directsound but I bet that has issues too.

In all grodfis2 got to the level of sequencing and playing 8 trakcs with 8 instruments and apart from the music data was coming in around 600 bytes. So directsound is ok but without using its advanced features it hardly seems worth it.
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on May 03, 2007
Quote...getting rid of clicking in the buffers...
Ideally you run the code to fill the buffers on a different thread which is waiting for Windows events triggered by the primary buffer crossing some boundaries, but that would be a lot more bytes.

Why does COM take up so much more space?  Because of the GUIDs and the need to import the IUnknown interfaces?

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on May 03, 2007
Jim,

I'm not sure. Im not a PC programmer so I dont know a lot about this stuff, it would be a good area for DBF to investigate! I tried to produce a COM based exe once and it seemed to me that some sort of code is placed before your own, like a redirection table maybe? I looked at the asm but being no expert I couldn't tell what it was about. This is the problem with not being a programmer by trade, you run out of knowledge. For SAPI, the speech api, its cost me around 350 bytes after compression...frankly unacceptable in 1k or 4k.

I should add this was under GCC, I never tried with VC++ - maybe microsoft, owning COM, are smarter? Fancy trying it Jim?

Damn I try to quit the scene and dbf C++ thread turns into a research group for intros! Bloody hell this is the coolest board on the planet.

Chris
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Jim on May 03, 2007
Sounds like a mission :)

Jim
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Rbz on May 14, 2007
I already did my tests with playsound and directsound, and I'll be using directsound, I'm finding it very powerful (as it should be) and I have coded a basic player and working on a tracker.

Player features:
- 4 sound channels (can be expanded to 8 channels)
- 8 gm samples
- 32 rows per page
- 8 pages
- 32 postions for pattern order
- Player runs in real time, yeah I can easily add synch with intro effects.

There's no fx added yet, only volume control for each sample.

It's very very simple player, but it can able to produce some sort of music ;) , oh yeah and very tiny - around 650~700 bytes for player and music data.
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: taj on May 14, 2007
Quote from: rbraz on May 14, 2007

There's no fx added yet, only volume control for each sample.

It's very very simple player, but it can able to produce some sort of music ;) , oh yeah and very tiny - around 650~700 bytes for player and music data.


Try adding reverb or any fx and see what size your exe jumps to - my guess is you'll be >1k.

Well done on producing all that!

Chris
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Rbz on May 15, 2007
QuoteWell done on producing all that!
Thanks, just looking to what you already did, make me motivated to code my own!

QuoteTry adding reverb or any fx and see what size your exe jumps to - my guess is you'll be >1k.
Ok, I'll see what I can do...

Btw, do I really need to add midi notes (change frequency) for the samples, you know, I'm not a musician and I don't know if I *must* add this...  ???
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Raizor on June 22, 2012
Excuse the necro-posting, but I've been playing around with GM.DLS and using Jim's example program as a reference.

I noticed a little problem when processing extra elements in GM.DLS RIFF file. Sometimes the payload (data) for an entry is marked as having an odd number of bytes. In this case, the data is padded with an extra byte in the DLS file. This was causing me a few problems, which I resolved by changing the 'dlist' method slightly:

I changed

      riff = (unsigned int *)((unsigned char *)riff + 8 + *(riff+1));

to

      unsigned int dataSize = *(riff+1);
      if (dataSize % 2 != 0) dataSize++;
      riff = (unsigned int *)((unsigned char *)riff + 8 + dataSize);

It then takes into account the extra padding byte and enables you to process any of the elements without issue. Just for reference, the issue I experienced was due to the uneven ICOP entry in the INFO lists.

I thought that this may prove helpful to someone at some point. Depending on how deep I end up delving with this, I may have a C# application similar to Blackpawn's at some point. If so, I'll post a link to it on the forum.
Title: Re: Extracting gm.dls samples for tiny demo trackers
Post by: Raizor on June 23, 2012
I had a little trouble tracking down the PDF specs document for DLS files (lots of dead links). I've attached it to this post.