Project : convert yamaha YMxxx FM to saturn scsp FM

about adpcm & sbl, sega didn't provide the sources of the adp library. in order to use it i converted object from coff to elf :

objcopy --remove-leading-char --input-target=coff-sh --output-target=elf32-sh adpmobuf.o adpmobuf.obj
objcopy --remove-leading-char --input-target=coff-sh --output-target=elf32-sh adpstbuf.o adpstbuf.obj
objcopy --remove-leading-char --input-target=coff-sh --output-target=elf32-sh adpunit.o adpunit.obj
renamed .obj to .o
ar -a sega_adp.a *.o

then when i try to use adp function i always fail to build my binary :

saturn/saturn.o: In function `main':
saturn.c:(.text.startup+0x208): undefined reference to `ADP_DecMono'
collect2.exe: error: ld returned 1 exit status

any idea what's wrong ?
 
About the sound area map, I did some reading over the weekend to try to figure out how it works :
From what I understand, one tone takes 8 bytes of map data, and the first adress should be at 0x0b000.
Byte 0 : MSB at 0 = used, bits 6,5 and 4 are for the type, with 0 being tone data. The next 4 bits are the bank ID number (so 0 to 15).
Bytes 1, 2, 3 : Last 4 bits of byte 1 are unused, the remaining bits are for the adress of the tone in memory.
Byte 4 : MSB is 0, the rest seems unused.
Bytes 5 to 7 : size of the tone data.
You then need to use end codes for the area map and for the global map : so 0xff and another 0xff.

Which gives me something like that for a simle jumping sound (9628 bytes) :
char sound_map[]= {0x00,
0x00, 0xb0, 0x00, //Start adress
0x00, //except for the MSB, seems unused
0x00, 0x25, 0x9c, //size of the tone data
0xff, 0xff //end code
};

Now, using SGL, I can't figure out how to play a sound using tone only (no sequence data).
Do I have to use a sequence for that?
How to trigger the sound?

EDIT : I also tried PCM playback for sounds in the audio RAM and, for SGL at least, the sound get distorted like crazy, while playing back from the main RAM has no issues.
Unless there is another way around this, using sequences is the only way.
 
Last edited:
You use the MIDI Direct Control command to send MIDI messages to the sound driver. For basic sample playback, directly controlling the SCSP is also pretty straightforward (I posted an old basic example earlier in the thread).
 
You use the MIDI Direct Control command to send MIDI messages to the sound driver. For basic sample playback, directly controlling the SCSP is also pretty straightforward.
Thanks for the reply, but do you have any examples?
I have my aiff files in sound RAM (my tone bank), but how can I trigger it without a sequence?
Can it be done or do I have to create more data?
Thanks!

EDIT : Ok, I saw the example, so the sound source is a PCM file?
 
Last edited:
You use the MIDI Direct Control command to send MIDI messages to the sound driver. For basic sample playback, directly controlling the SCSP is also pretty straightforward (I posted an old basic example earlier in the thread).
Ok, thanks for your help!
I got it working using SBL and Midi direct control commands. It seems to lose some sounds once in a while, but it works fine with the data generated using the Tone editor and it can playback way more sounds than using PCM streaming from main RAM.

My test function (after loading the sound driver, the map and the tone data in the sound RAM) :
Code:
void TEST_AUDIO(Uint8 nb)  //Nb = number, both for voice and channel
{
   SND_CtrlDirMidi(0x02, 0x00, 0x03, nb, 0x20, 0x00);  //Bank change. Not needed if you have only 1 bank
   SND_CtrlDirMidi(0x02, 0x00, 0x04, nb, nb, 0x00);  //Voice change. That's the sound you want to play (16 values max)
   SND_CtrlDirMidi(0x02, 0x00, 0x00, nb, 60, 127); //Stop playing the previous sound on that channel
   SND_CtrlDirMidi(0x02, 0x00, 0x01, nb, 60, 127); //Start playing the current sound on the passed channel
}
 
Ok, thanks for your help!
I got it working using SBL and Midi direct control commands. It seems to lose some sounds once in a while, but it works fine with the data generated using the Tone editor and it can playback way more sounds than using PCM streaming from main RAM.

My test function (after loading the sound driver, the map and the tone data in the sound RAM) :
Code:
void TEST_AUDIO(Uint8 nb)  //Nb = number, both for voice and channel
{
   SND_CtrlDirMidi(0x02, 0x00, 0x03, nb, 0x20, 0x00);  //Bank change. Not needed if you have only 1 bank
   SND_CtrlDirMidi(0x02, 0x00, 0x04, nb, nb, 0x00);  //Voice change. That's the sound you want to play (16 values max)
   SND_CtrlDirMidi(0x02, 0x00, 0x00, nb, 60, 127); //Stop playing the previous sound on that channel
   SND_CtrlDirMidi(0x02, 0x00, 0x01, nb, 60, 127); //Start playing the current sound on the passed channel
}
Great job, XL2!!! any more details (or just source code) ? I may use that way if it allows to override the 8 PCMs limit.
 
I'm working on my engine to open source it, so I quickly create a guide but I didn't put much work in it.
Code:
*********************************************
Z-TREME ENGINE AUDIO IMPLEMENTATION - README
2018-04-05
*********************************************

Using audio is a bit tricky and it might take you a while to get it right.
Most homebrew apps simply use PCM audio from the work ram and DMA it in the sound RAM buffer area.
The issue with this is that it wastes precious RAM, adds CPU overhead and hogs the B-BUS with DMA transfers (the same bus that connects the SH2 CPUs with the VDP1 and VDP2).

The best solution is to use the audio processors and the audio RAM with MIDI sequences - but instead of using sequences, we will use direct MIDI commands to the sound driver.
Sadly, I won't have time in the near future to write an app to replace the Sega Sound Tools, so right now the solution is tricky and not user-friendly.
All the Sega Sound Tools apps are for old 68K Macs and they require extra hardware (like a sound box).
By using an emulator, we can do almost everything we need for sound effects.

The solution is the following :

1) Download an old Mac emulator (68K). I use BASILISK II : https://basilisk.cebix.net/

2) Set your MAC OS 7 ROM

3) Download the Sound Tools : https://antime.kapsi.fi/sega/docs.html

4) Make sure you have .AIFF (Big endian) audio that you want to use. It will all be put in sound RAM (512 KB), so make sure you have no more than about 400 KB.

5) Use the Tone Editor to create your tone data : https://antime.kapsi.fi/sega/files/ST-068-R1-042594.pdf
   You can also look at the SGL tutorial documentation (Page 2-8) to see how to use it : https://antime.kapsi.fi/sega/files/ST-237-R1-051795.pdf
   Note that you should use only 1 bank (or switch banks ingame) and keep all the sounds in different layers.
   YOU NEED to offset the base pitch! Your first value should be C4 (60) for both beginning and end in the layer section.
   Each subsequent sound should increase that value by 1.
   Make sure you change the base pitch with the same increase. If all your audio is 22,050 khz, your base pitch should be 72 or 84 for 11,025 khz.
   Follow the SGL guide closely as it's pretty complicated the first time!

6) Create your MAP file : you can use the Sound simulator to generate one.
   Look again at the SGL tutorial documentation (Page 2-29)

7) Put your files (MAP, Sound driver and Tone data) in your CD folder, under the SOUND subfolder.

8) Tweak your Z-TREME Engine ZT_AUDIO.c file if you want to use different names, or just use the default names for your files and replace them.
   Make sure that you modify the length of the files as needed.

9) Ingame, just call the sound function when you need to play a sound.
   If you have more than 16 sounds, you will need to do a bank change depending on where your sound is.
   The sound function will stop the previous sound (say sound 60) if the same sound (again sound 60) is called twiced. By using MONO sound, you can play the same sound twice at the same moment, else it will be once only.
   If you wish to have the same sound played on several channels, just remove the MIDI stop command from the ZT_AUDIO.c file, but make sure you clear the channels manualy as needed.
   I suspect that by using the wave editor you might be able to put an end comand at the end of the sound, so that the channel clears itself, but I haven't tried it yet.
   The sound will stop on it's own, but the channel won't be cleared as it is now, which isn't a very huge deal.

Enjoy!

For the commands, by using 1 voice and multiple layers (16 max) it should be like that :
Code:
/** NOTE : The current function doesn't clear the channels after the playback, only after you play the sound again. There must be a setting in the tone editor I missed, but for now we just clear it first... **/
void ztPlaySound(Uint8 SFX) //The direct Midi control is as follow : SndRet SND_CtrlDirMidi(SndSeqNum, SndSeqPri, Uint8 MidiCommand, Uint8 MidiChannel, Uint8 pitch, Uint8 velocity);
{
    SND_CtrlDirMidi(0x02, 0x00, MidiNoteOff, Channel1, SFX, 127); //Stop the note (clears the channel)
    SND_CtrlDirMidi(0x02, 0x00, MidiNoteOn, Channel1, SFX, 127); //Plays the note (it will stop playing once it's done, but won't clear the channel)
}

So to call it you could do something like : ztPlaySound(60+soundID);
Your base note is 60, so all subsequent sounds should add 1 to it (so 60 will play sound 0, 61 plays sound 1, 62 plays sound 2, etc.).
I hope this makes sense!
 
  • Like
Reactions: vbt
Great job, XL2!!! any more details (or just source code) ? I may use that way if it allows to override the 8 PCMs limit.
Anyone, by any chances, managed to convert midi files (other than the Sega demos) to sequences?
I always get error messages about program change being first or something, so I can't use midi music.
 
are you speaking about that tool ? i don't even manage to display a midi file into the list.

upload_2018-5-10_3-40-58.png


There is some limitations but it doesn't explain why i can't my midi files, i tried .mid & .midi extensions.

upload_2018-5-10_2-49-57.png
 
  • Like
Reactions: XL2
are you speaking about that tool ? i don't even manage to display a midi file into the list.

View attachment 4571

There is some limitations but it doesn't explain why i can't my midi files, i tried .mid & .midi extensions.

View attachment 4570
Thanks for the info, I forgot about that powerpoint, it's quite useful!
I have the same problem as you do, but I downloaded a MIDI editor for Mac and used it to read Midi files and save them with it, which allows me to get the files on the list, but I get errors when I try to convert to the Sega format.
Maybe I'll have to find a way to get the programs Sega suggested, but since we don't have all the needed hardware maybe it can't be done.
 
XL2, you're right, i installed a midi player and can add midi files to the converter, then the error happens.
I will try multiple midi generators and see if something works.

upload_2018-5-10_19-59-22.png


EDIT : after using a converter from TYPE 0 to TYPE 1

upload_2018-5-10_20-8-48.png
 
Last edited:
XL2, you're right, i installed a midi player and can add midi files to the converter, then the error happens.
I will try multiple midi generators and see if something works.

View attachment 4572

EDIT : after using a converter from TYPE 0 to TYPE 1

View attachment 4573
Yeah, I get the exact same error.
Having midi audio would be great to allow streaming other stuff (such as visibility data) and it doesn't have SH2 overhead, unlike PCM streaming.
Creating an audio converter would be the best option, but it's not a small task!
 
I've just did manually a working midi from the file i took on internet

upload_2018-5-10_21-48-2.png


Thanks to the CyberWarriorX tool (recently updated by MistyM), i compared working an not working files.
The result is you need to add 1 event before each first "Program Change" of a track, the type must be "Control Change" and the Value "32-Bank Select LSB"

Try the two files :
first one is Type 0, second one is Type 1 with the bank selection.

https://ufile.io/1pvw1
 
  • Like
Reactions: XL2
I've just did manually a working midi from the file i took on internet

View attachment 4576

Thanks to the CyberWarriorX tool (recently updated by MistyM), i compared working an not working files.
The result is you need to add 1 event before each first "Program Change" of a track, the type must be "Control Change" and the Value "32-Bank Select LSB"

Try the two files :
first one is Type 0, second one is Type 1 with the bank selection.

https://ufile.io/1pvw1
Nice!
Does it also convert the sound bank (the instruments)?
Or does that also need to be done manually ?
 
m68k-elf

Development:
Thanks cWx for linker script and help
Includes gcc 4.8 elf compiler environment
compiles main.c in PROJ folder to a binary file
the 68k_test is a jo engine demo which will load the binary to sound RAM and run it
it will print the memory written by the program on-screen.

I will be going further....
 
  • Like
Reactions: XL2
yes i've discussed with some high skilled french guy and asked also on irc, the idea is something like this for an ym2203 :

- 3 channels with 4 operators becomes 3x4 pcm voices
- create a sinusoidal tone for the 12 pcm voices
- write some stuff directtly to scsp registers
- merge all to a fm channel to reproduce fm synthesis

well i don't have such knowledges so i'd need help
I did this a long time ago. You need to have a sine wave sample that is 3 cycles long. I used a 6KB sample (1024 16-bit points times 3). The address pointer of the SCSP should point to the middle one (because the address shifts forward or backward by up to 1 cycle length during phase modulation).

Set the frequency/volume/envelope according to YM2203 settings. Then setup the algorithm by connecting the slots together with the $0E register. Here is one example of some register settings:
Code:
; a 4-op FM melody instrument

        ; slot 8          (2)
        dc.w $0108,$2B9F
        dc.w $010A,$0004
        dc.w $010C,$0040
        dc.w $0110,$2000
        dc.w $0116,0

        ; slot 9           (4)
        dc.w $0128,$2CDF
        dc.w $012A,$00CA
        dc.w $012C,$0030
        dc.w $0130,$2800
        dc.w $0136,0

        ; slot 10          (1)
        dc.w $0148,$1C5F
        dc.w $014A,$000A
        dc.w $014C,$0020
        dc.w $014E,$D79E
        dc.w $0150,$1800
        dc.w $0152,$5230

        ; slot 11        (3)
        dc.w $0168,$2458
        dc.w $016A,$000A
        dc.w $016C,$0020
        dc.w $016E,$E79E
        dc.w $0170,$1800
        dc.w $0172,$5230
 
  • Like
Reactions: vbt
I did this a long time ago. You need to have a sine wave sample that is 3 cycles long. I used a 6KB sample (1024 16-bit points times 3). The address pointer of the SCSP should point to the middle one (because the address shifts forward or backward by up to 1 cycle length during phase modulation).

Set the frequency/volume/envelope according to YM2203 settings. Then setup the algorithm by connecting the slots together with the $0E register. Here is one example of some register settings:
Code:
; a 4-op FM melody instrument

        ; slot 8          (2)
        dc.w $0108,$2B9F
        dc.w $010A,$0004
        dc.w $010C,$0040
        dc.w $0110,$2000
        dc.w $0116,0

        ; slot 9           (4)
        dc.w $0128,$2CDF
        dc.w $012A,$00CA
        dc.w $012C,$0030
        dc.w $0130,$2800
        dc.w $0136,0

        ; slot 10          (1)
        dc.w $0148,$1C5F
        dc.w $014A,$000A
        dc.w $014C,$0020
        dc.w $014E,$D79E
        dc.w $0150,$1800
        dc.w $0152,$5230

        ; slot 11        (3)
        dc.w $0168,$2458
        dc.w $016A,$000A
        dc.w $016C,$0020
        dc.w $016E,$E79E
        dc.w $0170,$1800
        dc.w $0172,$5230
wow i'm impressed maybe for you it's easy, would you mind helping me on such thing ? do you have a working sample ?
actually, i moved to streaming pcm which is not so good.
 
I posted assembly source for the demo that used it here: http://www.hyakushiki.net/thedung.zip

But at the time (2013) it didn't work in any emulator, only by transferring it to the Saturn with Saturn USB. Is there an emulator that handles FM sound now? If so then I could try to make a simpler program to demonstrate FM sound.
 
Back
Top