I'm interested in creating a softsynth using Gm.dls wave data, for use in 4k intro development. However, I've never done any audio programming, so I'm not sure what approach I should use, and what type of filters are common, or even how to playback the data. My approach is similar to this:
-Samples (will contain the wave data from Gm.dls. In the stored format, only the Gm.dls offset will be stored, including looping data)
-Instrument (pointer to a sample, plus parameters for filter effects)
-Patterns (series of notes)
-Music (sequence of patterns in multiple simultaneous channels)
Then somehow have an update function that is called each frame, that calculates a small audio buffer sequence and sends it to the sound card.
So, the situation where I am at now, is that I've successfully created a program that can read and parse Gm.dls into appropriate wave data. However, I know that the wave data includes wave looping/loop length information, and I'm not sure how to extract this, and it is obviously critical, or else the samples often seems cut short. Additionally, is there a way using directsound to automatically take into account this looping info, and add parameters such as ramp and volume? Or do I automatically have to create the buffer myself? Additionally, I'm not even sure how to manipulate the sample audio data, and how much directsound can do for you. Any pointers would be welcome. In the meantime, here is my code for extracting gm.dls audio data (without loop data, which I don't know how to extract). It is not very optimized, as that will be done last. The program extracts the samples, displays the sample names and offsets, then you can type in a number to hear the corresponding wave data, and "q" to exit. It has the negative drawback of loading the absolute address for gm.dls, but that would take like 3sec to fix.
#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <windows.h>
using namespace std;
struct gmSample
{
short index;
DWORD offset;
long loopStart;
long loopLength;
};
int main()
{
ifstream input("C:\\Windows\\System32\\drivers\\Gm.dls", ios::in | ios::binary);
if(input.fail()) {
cerr << "Could not open Gm.dls";
return 1;
}
input.seekg(0, ios::end);
int _length = input.tellg();
input.seekg(0, ios::beg);
unsigned char* _data = new unsigned char[_length];
input.read(reinterpret_cast<char *> (_data), _length);
input.close();
typedef map<char*, gmSample> SampleMap;
typedef map<int, char*> SampleInd;
SampleMap samples;
SampleInd indicies;
int index = -1;
unsigned char* dt = _data;
while(dt < _data + _length - 64) {
if(*(DWORD *)dt == 'TSIL') {
*(DWORD *)dt = 'FFIR';
dt+=8;
if(*(DWORD *)dt == 'evaw') {
*(DWORD *)dt = 'EVAW';
gmSample sample;
sample.offset = DWORD(dt-8) - DWORD(_data);
sample.index = index++;
char* name = new char[8];
memset(name, 0, 8*sizeof(char));
memcpy(name, dt-16, 7*sizeof(char));
samples.insert(SampleMap::value_type(name, sample));
indicies.insert(SampleInd::value_type(index, name));
}
}
dt++;
}
for(SampleMap::iterator itor = samples.begin(); itor!=samples.end(); itor++) {
cout << itor->first << '\t' << itor->second.offset << endl;
}
string io("1");
while((io.compare("quit") != 0) && (io.compare("q") != 0)) {
int num = atoi(io.c_str());
gmSample smpl = samples.find(indicies.find(num)->second)->second;
PlaySoundA((const char*)(_data+smpl.offset), NULL, SND_MEMORY);
cin >> io;
}
samples.clear();
delete [] _data;
return 0;
}
PS: I'm also looking for a musician who would be willing to compose a tune for use in a PSP demo to be released soon (Any format is fine).



