SEQ64 - Sequenced music editor for first-party N64 games

Started by Sauraen, November 17, 2014, 06:07:07 PM

Previous topic - Next topic

SubDrag

I assume you've seen the N64 Sound Tool I made it?  It has a good chunk of the format done for the EAD games, but it can't import.

Sauraen

Merry Christmas! A little MIDI import for everyone:

https://soundcloud.com/sauraen/wassail-song-castletown-market

Quote from: SubDragI assume you've seen the N64 Sound Tool I made it?  It has a good chunk of the format done for the EAD games, but it can't import.
I looked at it briefly, but not in depth, and not at the source code. Does it do actual sound (ADPCM) import/export? That's something I haven't even considered in my program.

In the next couple days I plan to write up a couple full wiki pages on my project's site describing all the commands in Audioseq format, and all the data structures in Audiobank format--I've figured out more than what was previously known in both cases.

SubDrag

Nice midi!

It supports VADPCM import and export (although not predictor generation, they're fixed) for a couple of the formats, the standard one, and N64 Wave Pointer types.  For Zelda (EAD games), I only support export, I don't have the format 100% flushed out, so it doesn't support import.  Some adventurous people have manually replaced samples heh.  The ADPCM is identical for all these formats (except musyx, which is also supported for export only).

Oh then what did you mean by sound bank support in your tool if not the samples import/export ? 

Sauraen

Quote from: SubDragOh then what did you mean by sound bank support in your tool if not the samples import/export ?
In the Zelda Debug ROM, the file with all the instrument sets (including the actual instrument definitions, except for samples) is named Audiobank, and the file with the actual samples is named Audiotable. These names are not present in the other games, but they're organized the same way. Maybe I will eventually go for samples editing, but I didn't want to get into DSP stuff, I've only had one course on it and I don't understand it very well.

I will check out your program, I already downloaded it. Do you have any instructions or wiki anywhere on how to use it?

SubDrag

Ah ok, I didn't realize was a difference.  Yeah mine is mainly intended at samples, and then the midi tool deals with games midis. In theory together someone could make a soundfont and play midis through it.  EAD is mostly supported on import, but there's fields I don't understand.  The EAD games (well Zelda) has both percussion and regular sounds in the same banks. 

Basically:
File->Open Known Game, pick your game, open that ROM.  It uses the ini file to locate the sounds based corresponding to that name.  When it's loaded, you can play sounds or rip them.  It has sound banks, with instruments inside bank, and then inside each instrument, sounds, and then inside sound, sometimes they have up to 3 sounds inside (maybe different pitches, not sure why).   Some games (not EAD games) you can import and inject in place, then File->Save ROM when done.

Sauraen

Quote from: SubDragIt has sound banks, with instruments inside bank, and then inside each instrument, sounds, and then inside sound, sometimes they have up to 3 sounds inside (maybe different pitches, not sure why).
This sounds a lot like the Audiobank format in EAD games, only that the samples are stored in a separate file. Though there is some sample data in two data structures in each sound definition--maybe these are the predictors? I don't know much about how the actual sample playback works, do you have any more information?

I played with your program a bit, it looks good! I had to adjust the sample rate manually for many sounds, though--there's no data in the structs internally that specifies the sample rate in some form?

I have figured out more of what the EAD bank format is, here's my notes, again lots of information originally from DeathBasket and messiaen:


================
AUDIOBANK FORMAT
================

Audiobank Index
^^^^^^^^^^^^^^^

For SM64, etc:

typedef struct{
  uint16 maybe_version; //Usually 1
  uint16 NUM_BANK;
  AudiobankIndex_Entry entries[NUM_BANK];
} AudiobankIndex_Hdr;

typedef struct{
  Audiobank* addr; //Relative to the start of Audiobank
  uint32 len;
} AudiobankIndex_Entry;


For Zelda, etc:
typedef struct{
  uint16 NUM_BANK;
  uint16 zeros[7];
} AudiobankIndex_Hdr;

typedef struct{
  Audiobank* addr; //Relative to the start of Audiobank
  uint32 len;
  uint8 unknownA = 0x02; //Unknown
  uint8 unknownB; // Unknown, 02 for most sequences, 01 for a few (normal) sequences, 00 for Master Instrument Set and Actor Sounds
  uint8 samplesetidx; //Sample Set Index number
  uint8 unknownD = 0xFF; //Unknown
  uint8 NUM_INST; Number of instruments (i.e. all instrument numbers >= this number are invalid, though some less than this are also invalid when actually reading Audiobank; this is the length of the array of instrument pointers)
  uint8 NUM_DRUM; Number of drums (same as for instruments; length of array of drum pointers)
  uint8 unknownG = 0x00; //Unknown
  uint8 NUM_SFX; Number of Sound Effects (same as above) (Unknown what these sounds actually are, maybe they're environment SFX or something?)
} AudiobankIndex_Entry;


Audiobank File
^^^^^^^^^^^^^^
Sections are (always?) padded with zeros at the end to reach an address an even multiple of 0x10.

***

For SM64:
typedef struct{
  uint32 NUM_INST;
  uint32 unknown_zero_1;
  uint32 unknown_zero_2; //Is 1 in first instrument set
  uint8 unknown1 = 0x19;
  uint8 unknown1 = 0x96;
  uint8 unknown1 = 0x02;
  uint8 unknown1 = 0x14; //Slightly different in MK64, etc.
} Audiobank_Hdr;

For Zelda:
typedef struct{
  //no data--0 length
} Audiobank_Hdr;

***

All pointers are relative to the start of this struct!
(For Zelda, this is also the beginning of the file)

For SM64:
typedef struct{
  Something* unknown_zero_3;
  Audiobank_InstEntry* instlist[NUM_INST];
} Audiobank_Main;

For Zelda:
typedef struct{
  Audiobank_DrumList* drumptr;
  Audiobank_SFXList*  sfxptr;
  Audiobank_InstEntry* instlist[NUM_INST];
} Audiobank_Main;

***

typedef struct{
  Audiobank_DrumEntry* drumlist[NUM_DRUM];
} Audiobank_DrumList;

***

typedef struct{
  Audiobank_Sound sfxlist[NUM_SFX];
} Audiobank_SFXList;

***

typedef struct{
  uint8 unknown1; //Always? 00 in ROM, 01 when loaded to RAM
  uint8 splitpoint1;
  uint8 splitpoint2;
  uint8 decaytime; //Claimed, untested
  Audiobank_PatchProps* props;
  Audiobank_Sound splits[3]; //Sounds to use before first split point, between two split points, and after second
} Audiobank_InstEntry;

***

typedef struct{
  Audiobank_PatchPropsEntry ppentries[4];
} Audiobank_PatchProps;

typedef struct{
  int16 unknown1; //This halfword is read
  uint16 unknown2; //and shortly after, this halfword is read
} Audiobank_PatchPropsEntry;

***

typedef struct{
  uint8 unknown1; //Usually all the same for a sequence
  uint8 unknown2; //Usually different for each different drum sound
  uint8 unknown3; //Always? 00
  uint8 unknown4; //Always? 00
  Audiobank_Sound drumsound;
  Audiobank_PatchProps* props;
} Audiobank_DrumEntry;

***

typedef struct{
  Audiobank_SampleHdr* sample;
  uint32 tuning; //Unknown format, but increases with pitch
} Audiobank_Sound;

***

//For SM64:
typedef struct{
  uint32 unknown_zero_1;
  Audiotable_Sample* data; //Offset from
  Audiobank_SampleStr2* str2;
  Audiobank_SampleStr1* str1;
  uint32 samplesize; //May only be lower 16 bytes
  uint32 zeros[3];
} Audiobank_Sample; //also known as "Unknown Data Structure"

//For Zelda:
typedef struct{
  uint8 unknown1;
  uint24 samplesize; //Not sure whether this is just the lower 16 bits
  Audiotable_Sample* data; //Offset from base address from Sample Set Index
  Audiobank_SampleStr2* str2;
  Audiobank_SampleStr1* str1;
} Audiobank_Sample; //also known as "Unknown Data Structure"

***

typedef struct{
  uint32 size1;
  uint32 size2;
  Audiobank_SS1Block blocks[size2];
} Audiobank_SampleStr1;
/*
Structure 1:
First two words are accessed as words immediately when reading structure
First word is left shifted 4, then multiplied by second word, result is masked to 0x00FFFFFF, or'd with 0x0B000000 (here it's now 0B000040), and then this is stored in some working RAM
The rest of the data does not appear to be read during normal music playback
*/
typedef struct{
  int16 some_audio_data[0x10]; //32 bytes of what looks like 16-bit 2s complement values that make a waveform; probably ADPCM
} Audiobank_SS1Block;

***

typedef struct{
  uint32 maybe_loop_start;
  uint32 maybe_loop_end;
  uint32 unknown_FFFFFFFF; //Always?
  uint32 unknown_00000000; //Always?
  Audiobank_SS2Block block[zero_or_one]; //Zero if first word is 0, exists if first word is nonzero
} Audiobank_SampleStr2;
/*
Structure 2:
00003ADB
000059A4: addressed as word; possibly a length or sub-address for samples? The next thing accessed is the address for samples in Audiotable from UDS.
FFFFFFFF: read as word, used for a branch condition (probably -1, not data)
00000000
The rest of the data does not appear to be read during normal music playback
*/
typedef struct{
  int16 some_audio_data[8]; //16 bytes of what looks like 16-bit 2s complement values that make a waveform
} Audiobank_SS2Block;



SubDrag

I guess they never looked at my stuff, and I didn't know they were researching it either.  They definitely had some stuff right, but didn't understand the audio itself - what they have as unknown is probably the predictors, and they didn't seem to connect to the samples (also, comparing to the N64 SDK format used by most games is useful).   I also identified the looping information (mainly my tool helps people make soundfonts, so they needed that), and knew what to "do with the data".  Note Super Mario 64 is actually more or less fully supported in my tool, for export and import is working too (couple unknowns but not much), but EAD/Zelda format got much more complex, since they added percussion, so I never made it to the import stage. 

There may be something that adjusts sampling rate in their data, and I guess I never found it and wasn't sure, but I did in some of the other formats.  It's not always simple the way they define that.  It's fairly simple algorithm actually the n64 used (harder to encode, I brute force it to get best values, and use fixed predictors, but it gets something reasonable).  I don't know what you intended to support in your tool, but it would be nice to support import in my tool one day and know the pieces, though my goal now is to rip/play all n64  games sounds.  There's still some weirdness in the sound tool with Zelda - seems like some banks had something strange, like maybe some samples used one tbl, and some another.  In ever fully flushed it out, but ripping the samples was good. 

Hopefully it will help you fill in some of the gaps in your document there too.

Sauraen

Quote from: SubDragThey definitely had some stuff right, but didn't understand the audio itself
When I said the above was my notes, I got the overall structure from DeathBasket's site but I figured out some things myself, like the existence of a third class of sounds (besides instruments and drums) which I called SFX because I didn't know how they were used.

But this is the point of a forum, we can collaborate and improve each other's work. :) So I have this:

typedef struct{
  uint32 size1;
  uint32 size2;
  Audiobank_SS1Block blocks[size2];
} Audiobank_SampleStr1;
/*
Structure 1:
First two words are accessed as words immediately when reading structure
First word is left shifted 4, then multiplied by second word, result is masked to 0x00FFFFFF, or'd with 0x0B000000 (here it's now 0B000040), and then this is stored in some working RAM
The rest of the data does not appear to be read during normal music playback
*/
typedef struct{
  int16 some_audio_data[0x10]; //32 bytes of what looks like 16-bit 2s complement values that make a waveform; probably ADPCM
} Audiobank_SS1Block;

***

typedef struct{
  uint32 maybe_loop_start;
  uint32 maybe_loop_end;
  uint32 unknown_FFFFFFFF; //Always?
  uint32 unknown_00000000; //Always?
  Audiobank_SS2Block block[zero_or_one]; //Zero if first word is 0, exists if first word is nonzero
} Audiobank_SampleStr2;
/*
Structure 2:
00003ADB
000059A4: addressed as word; possibly a length or sub-address for samples? The next thing accessed is the address for samples in Audiotable from UDS.
FFFFFFFF: read as word, used for a branch condition (probably -1, not data)
00000000
The rest of the data does not appear to be read during normal music playback
*/
typedef struct{
  int16 some_audio_data[8]; //16 bytes of what looks like 16-bit 2s complement values that make a waveform
} Audiobank_SS2Block;


And you have this in N64AIFCAudio.h:

struct ALADPCMBook {
        unsigned long             order;
        unsigned long             npredictors;
        signed short* predictors;
};

struct ALADPCMloop {
        unsigned long             start;
        unsigned long             end;
        unsigned long             count;
        short     state[16];
unsigned long unknown1;
};

These seem to me to be likely the same. But I don't want to just pore over your source code until I find tidbits like this--where did you get the information that you based your program on (e.g. the names of these structs, or how these predictors work)? Is there some documentation somewhere describing ADPCM in general, or these structs in particular? You mention the N64 SDK, do you have a copy of it?! I don't mean to sound like a newbie, but I am pretty new to this scene, so please let me know where you get your info.

My program was originally for the purpose of creating custom music in Ocarina of Time with the existing sounds of the game. Once I saw that other games used similar formats for sequences, I decided to support those as well. If the way of selecting instruments was like in General MIDI with globally-indexed programs (patches), I probably would have never looked at messing with Audiobank, I would have just put in an editable table mapping in-game instruments to General MIDI instruments and called it quits. But since you have to make an instrument set for each sequence that doesn't use similar instruments, the user has to be able to change those around. I still plan to have it focus on this sort of library editing, rather than import and export of sounds; but I'll see how it goes. I toyed with the idea of having it actually import/export from/to Soundfont (SF2) format; but that would be a lot more work, and I know someone would go and try to load the entire Merlin Vienna soundfont into Ocarina of Time. :)

SubDrag

Yeah those are from the SDK.  If you just search the name of the struct you should find it.  However, that's the extent of matching the SDK with the EAD format.  The SDK only covers the standard ctl/tbl format.  My tool force fits all the types to one ALBank type for simplicity.  Actually the algorithm for adpcm itself was reverse engineered by Ice Mario originally, although I later found out that emulation already did all that fun stuff, so you can see it in the audio ucode plugins.  They basically share the algorithm, predictors, and loop information, then the rest of the packaging and small details about each sound are vastly different.    EAD format added percussion too.  People have been asking me to auto-make sound fonts using the N64 Sound Tool for a long time. 

Sauraen

I'm going to need to use SEQ64 for some other projects I'm helping with, and some other people online have been asking me about it; so I'm dusting it off again for a while.

I found some source code and information about Yaz0 compression at http://www.amnoid.de/gc/ , which is the compression used in OoT/MM and maybe other games. So I'm starting with writing my own version of a Yaz0/Yay0 compressor/decompressor, and I'm going to integrate it into the File List view of SEQ64. I don't want to rely on closed source, platform-specific, questionably stable Windows command-line programs from 2005 to let people use my software, especially not for a game like Ocarina of Time.

I also have a friend who may be helping me with this project. Not sure if this will work out, but he wants to start by making a library for working with Soundfont files, so eventually we can have Audiobank import/export to Soundfont.

Any other suggestions--especially for quick things!--are welcome.

Solemn

Quote from: Sauraen on March 12, 2015, 09:27:15 AM
I'm going to need to use SEQ64 for some other projects I'm helping with, and some other people online have been asking me about it; so I'm dusting it off again for a while.

I found some source code and information about Yaz0 compression at http://www.amnoid.de/gc/ , which is the compression used in OoT/MM and maybe other games. So I'm starting with writing my own version of a Yaz0/Yay0 compressor/decompressor, and I'm going to integrate it into the File List view of SEQ64. I don't want to rely on closed source, platform-specific, questionably stable Windows command-line programs from 2005 to let people use my software, especially not for a game like Ocarina of Time.

I also have a friend who may be helping me with this project. Not sure if this will work out, but he wants to start by making a library for working with Soundfont files, so eventually we can have Audiobank import/export to Soundfont.

Any other suggestions--especially for quick things!--are welcome.

Well we already have a soundfont for OoT but we could use the midis which we don't have to pair things up and a Majora's Mask soundfont and midi rip would be nice. It's great you and your team are working on this as Super Mario 64 and Star Fox 64 could use some support as some formats are still unknown.  :)

Sauraen

Quote from: Solemn on March 12, 2015, 11:41:39 AM
Well we already have a soundfont for OoT but we could use the midis which we don't have to pair things up and a Majora's Mask soundfont and midi rip would be nice. It's great you and your team are working on this as Super Mario 64 and Star Fox 64 could use some support as some formats are still unknown.  :)
Super Mario 64 already has MIDI export/import working; I don't own Star Fox 64 so I can't test it myself, but someone else is welcome to.

I have not used this particular soundfont you mention, but I have used many soundfonts from SNES games, and many of them are quite poor, to the point of barely complying with the SoundFont format. (E.g. samples out of tune, messed up loop points so you get weird buzzing, etc.) If I included support for Soundfont import/export, it would be a direct copy of data from the games, not sampling each sound and reconstructing them into a soundfont. However, this is major work, and I'm pretty booked with commitments through the end of the summer.

I'm not sure how I'll deal with soundfonts anyway. I can't post copyrighted data, that has been exported from ROMs, publicly on my website; everything I've put up so far has been legal. For MIDIs it makes sense to say "if you want a song, export it yourself"--it's not very hard, and to make a collection of MIDIs would be very time-consuming. However, I can't really expect any person who wants to use the instrument samples to go through the process of making a whole SoundFont themselves. I'm sure there'll be someone else out there who will put up a site with MIDIs and SoundFonts from each of the supported games. :) Also I want to emphasize that seq64 is as focused on importing as on exporting--I'm sure some day we will see a video of OoT with Ganon's laugh replaced by "Damn son, where'd ya find this" and "Hyaa!" replaced with the air horn. :)

SubDrag

Were you able to get romdesc for the other games, that would be great!  I suspect is just a matter of making a proper romdesc, I would guess Star Fox similar to Zelda, and the others Mario, but I don't know this format very well.

Sauraen

Quote from: SubDragWere you able to get romdesc for the other games
Sorry, I haven't been working on this at all. School, part-time job, other projects. I did purchase cartridges of 1080 Snowboarding and Wave Race 64 so I can do the RomDescs of them at some point, though I'm not sure anyone cares about those games.

SubDrag

OK, well, I would be very interested in getting all these games going (for midis)!  I support the sound for the most part, with some minor work needed, not concerned about that, just midis and connecting to right sound numbers.  I suspect they are very similar to Mario/Zelda, the only difference is the instrument bank stuff.  I've been trying to get these midis going vs soundbanks.

May 20, 2015, 10:14:26 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

I believe these are Star Fox US 1.0s, though not sure how to tell the primitives:
<knownfilelist>
    <knownfile type="Audioseq Index" from_ft="0" address="785888" length="0"/>
    <knownfile type="Audioseq" from_ft="0" address="892976" length="240880"/>
    <knownfile type="Audiobank Index" from_ft="0" address="786960" length="0"/>
    <knownfile type="Audiobank" from_ft="0" address="1133856" length="122912"/>
    <knownfile type="Instrument Set Index" from_ft="0" address="787504" length="0"/>
  </knownfilelist>

They are ever so slightly different than Zelda.  I suspect with a tiny bit of your work could get it, I just don't know format well enough.

Looks like C4 will end a sequence, and 90-9F are Absolute Trk Ptr.  It sort of plays ok, not sure if it's every last command.  Just took Zeldas, and modded the one, added C4.

http://goldeneyevault.com/priv/Star Fox 64 (U) (V1.0).xml
http://goldeneyevault.com/priv/Pokemon Stadium 2 (U).xml


Also how does percussion track work in Zelda games?  What instrument does it load, does it have multiple for percussion or just one?


Based on the soundbank format, I am guessing these games also use seq format:
1080
Doubutsu no Mori (J) - 0x27130 is Seq data
F-Zero
F-Zero N64DD
Pokemon Stadium 2 (U) - Instrument Index 0x878C0, Bank Index 0x86F30, Seq Index 0x87020, Audiobank Index 0x86960, Seq 0x14D6660

I also posted my soundbank tool, I'm sure you can help, as you are really good with audio, at some of missing audio params, especially on Zelda.

http://goldeneyevault.com/viewfile.php?id=302

Sauraen

Glad someone is getting the hang of my program! I recently bought 1080 Snowboarding so I can check that one, but I don't own any of the other games you mentioned (despite being a developer of hacking tools, I don't pirate ROMs that I don't own).

I have been getting back into seq64 development a little recently; Google Code is shutting down (the entire service, not just my project), so I have to migrate the repository to GitHub, and I figured I'd put up a better version in the meantime. Right now I've been working on integrated Yay0/Yaz0 compression/decompression, so people don't have to run games (OoT and MM) through an external decompressor before using them. I also set up support for more byte orderings and ROM file types, and converting between them. Once I have this all working, I'll probably release it as a new version.

The thing I plan to work on after that, whenever I get a chance, is continuing/finishing Audiobank editing capabilities. It will really enhance MIDI export to have the instruments correct, but more importantly, it'll allow real homebrew music development in these games. I personally need this because I'm doing some music for Project Beta Triforce, and I need to be able to make custom banks to go with the music I write.

As far as your question, C4 is Channel Start; if parsing the sequence header is running into this command, it should have already stopped. If the last thing before it is a Jump instruction, you may have to make that the "end of sequence", since it may just loop over and over, and seq64 won't follow it in an infinite loop.

Percussion is complicated! From the sequence side it's easy: on a drum channel you get Instrument 127 (C1 7F), then Drumset Number (DC ??, usually 00--I'm not positive what this number does, as the banks can only have one drumset--maybe it's an offset within the drumset, since the drumset can be longer than 0x40). On the bank side, any "normal" instrument might be a percussion instrument, since it can have up to three sounds separated by split points; for instance Tambourine in Zelda is a regular instrument, with "shake", "closed", and "drum" as the three sounds. Then also, each bank has a Drumset, which consists of 0x40 pointers to sounds (usually many repeated but with different pitches). The designers made the mappings whatever they felt like, though interestingly enough in Majora's Mask they used something very close to GM drum mappings.

The Audiobank editor will allow mapping non-drum instruments to GM drums (e.g. the Tambourine above), and drum instruments to non-drum instruments (e.g. Timpani in Zelda is in the drumset, while in GM it's a regular program).

SubDrag

OK, so I did attempt to make an Ocarina soundfont (and similar games) using my new N64 Soundbank Tool - perhaps we can collaborate and help enhance it.

Definitely good to add de/compression, a bunch of the games have it and have this type midi.

So I did know about the splits and have that working in regular instruments, but percussion is confusing.  So for example, bank 3, at 0x00014390 in the decompressed ROM. There clearly is a duplication of key base, where different sounds have the same key base.  For example, 3F879C7C is seen multiple times (one for each different sound info) in this 0x40.  I was wondering if maybe the sequence itself had some sort of way of differentiating.  Otherwise, I can't figure out how the splits work here, besides just keybase, but since that duplicates, there is something odd going on.  I didn't see any DC command in midi without a 00 next to it.

Also, the ADSR data is very confusing, and I'm not sure my data is correct at all, and release time even worse.  Perhaps you can check out what I was doing.  Anyways, here's my attempt DLS of Bank 3, you can see how I just ended up right now, splitting drums by each sound offset into its own drum bank, but clearly that's wrong.  Maybe you can shed some light on that as well.

It would be good to see a nice soundbank import, I got Mario importing, but Zelda was a bit more complicated though similar, I never pursued it.

Here's from my Soundbank tool, bank 3, which goes with the overworld midis for example (2-17) etc

http://goldeneyevault.com/priv/OcarinaDecompressedExtractedSoundbankBank3.dls

greytrain

Hello! I'm having trouble using SEQ64. It's too large for my screen, the top and bottom parts are hidden and I cannot use the buttons and tabs (or move the window). I use a 15.6" laptop with 1366x768 (max) resolution and I don't have the option to change the DPI.

Sauraen

Due to Google Code shutting down, the project has moved to GitHub, and is now available at:

https://github.com/sauraen/seq64

Quote from: greytrainHello! I'm having trouble using SEQ64. It's too large for my screen, the top and bottom parts are hidden and I cannot use the buttons and tabs (or move the window). I use a 15.6" laptop with 1366x768 (max) resolution and I don't have the option to change the DPI.
Sorry for not seeing your post sooner! This would be nontrivial for me to change, the window layouts are pretty full as it is, and even without that, getting things to intelligently resize is not always easy.

July 30, 2015, 11:13:04 PM - (Auto Merged - Double Posts are not allowed before 7 days.)

Quick update, I have Audiobank reading internally working just about perfectly in Ocarina of Time. This is something I started months ago and then let sit for way too long. It's rare for there to only be a couple bugs and then for it to just work!

Right now it's parsing the Audiobank file according to the user-editable definition of the C structs that make it up. It converts the file to Juce ValueTree format--basically a binary version of an XML tree, which can be saved as text XML for debugging inspection. And it's working!



Next up is the inverse, writing the Audiobank file from this format. Then finally, editing!

Sauraen

I am proud to announce my first, and possibly the first, complete custom music import into Ocarina of Time that takes full advantage of Audioseq and Audiobank formats and approaches the quality of the original music in the game:

https://soundcloud.com/sauraen/pbt-wind-temple-in-engine

This is an original Wind Temple theme from Project Beta Triforce (areoblast43o9.wix.com/projectbetatriforce). It is indeed playing in engine--I overwrote the sequence and bank for End Credits II, and then changed the House of Twins music to point to it, which is where you're hearing this from.

The very latest build of seq64 that includes the last few changes for this will be up tonight or tomorrow at https://github.com/sauraen/seq64