Project : convert yamaha YMxxx FM to saturn scsp FM

vbt

Staff member
would someone help on this project? it needs some documentation, dev, testing.
such stuff would add sound to some emulated games on final burn alpha like :

- vigilante
- black tiger
- pang
- super pang

the fm calculation from mame/fba is really too slow for a saturn whereas it would be really fast with a simple conversion to the scsp fm. it would allow to port more games on fba saturn
 
Have you looked at the capabilities of the chips you want to simulate, and how they correspond to the SCSP?
 
Have you looked at the capabilities of the chips you want to simulate, and how they correspond to the SCSP?
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
 
Basic audio playback isn't too difficult, this is some code I experimented with many years ago. The audio data used 16-bit samples, which is why length/2 is used as the loop end address. For FM sounds I assume the process is similar, except that you have to set up the modulation sources, and that the slots used for modulation aren't connected to a mixer.
Code:
#include "types.h"
#include "scsp.h"

#include "sample.h"

int main(void)
{
  u16  *pSample = (u16*)data;
  
  /* Set up SCSP */
  /* Max volume. */
  SCSP_VERVOL = 0xf;
  
  /* Set slot data. */
  SCSP_SLOT_ARRAY[0].SALow = (u16)((u32)pSample & 0xffff);
  SCSP_SLOT_ARRAY[0].LSA = 0;
  SCSP_SLOT_ARRAY[0].LEA = ARRAY_LEN/2;
  SCSP_SLOT_ARRAY[0].Env1 = 0;
  SCSP_SLOT_ARRAY[0].Env2 = 0;
  SCSP_SLOT_ARRAY[0].Volume = SDIR_ON;  /* Ignore EG, TL, LFO etc. */
  SCSP_SLOT_ARRAY[0].Pitch = 0; /* Should play at 44100 Hz */
  SCSP_SLOT_ARRAY[0].Pan = (7<<13) | (4<<8);  /* Max DISDL */
  SCSP_SLOT_ARRAY[0].SlotCTL = KEY_ON | LPCTL_FWLOOP | (((u32)pSample >> 16) & 0xf);
  SCSP_SLOT_ARRAY[1].SALow = (u16)((u32)pSample & 0xffff);
  SCSP_SLOT_ARRAY[1].LSA = 0;
  SCSP_SLOT_ARRAY[1].LEA = ARRAY_LEN/2;
  SCSP_SLOT_ARRAY[1].Env1 = 0;
  SCSP_SLOT_ARRAY[1].Env2 = 0;
  SCSP_SLOT_ARRAY[1].Volume = SDIR_ON;  /* Ignore EG, TL, LFO etc. */
  SCSP_SLOT_ARRAY[1].Pitch = (-1 & 0xf << 11); /* Should play at 22050 Hz */
  SCSP_SLOT_ARRAY[1].Pan = (7<<13) | (0x14 << 8);  /* Max DISDL */
  SCSP_SLOT_ARRAY[1].SlotCTL = KYONEX | KEY_ON | LPCTL_FWLOOP | (((u32)pSample >> 16) & 0xf);
#if 0
  /* Test LFO effect. */
  SCSP_SLOT_ARRAY[1].SALow = (u16)((u32)pSample & 0xffff);
  SCSP_SLOT_ARRAY[1].LSA = 0;
  SCSP_SLOT_ARRAY[1].LEA = ARRAY_LEN/2;
  SCSP_SLOT_ARRAY[1].Env1 = EGHOLD_ON;
  SCSP_SLOT_ARRAY[1].Env2 = 0;
  SCSP_SLOT_ARRAY[1].Volume = SDIR_ON;
  SCSP_SLOT_ARRAY[1].Pitch = (-1 & 0xf << 11); /* Should play at 22050 Hz */
  SCSP_SLOT_ARRAY[1].Pan = (7<<13);  /* Max DISDL */
  SCSP_SLOT_ARRAY[1].LFOCTL = (4<<5) | (2<<8) | (0xf<<10);/* Max PLFOS (pitch), triangle waveform(PLFOWS), max LFO frequency */
  SCSP_SLOT_ARRAY[1].SlotCTL = KYONEX | KEY_ON | LPCTL_FWLOOP | (((u32)pSample >> 16) & 0xf);
#endif
  while(1)
  {
  ;
  }
  
  return 0;
}
 
well, YMxxxx to SCSP seems to be too complex, so i thought about another way to play sound / music.
the mame m1 tool is able to convert all sfx/music to wave. so would it be possible to play the wav/pcm file instead of emulating the sound chip ? but then how to know which soundtrack has to be played ?
 
well, YMxxxx to SCSP seems to be too complex, so i thought about another way to play sound / music.
the mame m1 tool is able to convert all sfx/music to wave. so would it be possible to play the wav/pcm file instead of emulating the sound chip ? but then how to know which soundtrack has to be played ?
Not 100% on topic, but do you know if there is a way to store PCM audio in the audio RAM?
I know that there is a buffer area for PCM, but you need to DMA it there each time you play a sound. Not wasting work RAM on audio would be great!
 
Not 100% on topic, but do you know if there is a way to store PCM audio in the audio RAM?
I know that there is a buffer area for PCM, but you need to DMA it there each time you play a sound. Not wasting work RAM on audio would be great!
i'd say yes, see that :

#define PCM_ADDR ((void*)0x25a20000)

PCM_PARA_WORK(&para) = (struct PcmWork *)&g_movie_work;
PCM_PARA_RING_ADDR(&para) = (Sint8 *)PCM_ADDR+0x40000+(0x4000*(i+1));
PCM_PARA_RING_SIZE(&para) = RING_BUF_SIZE;
PCM_PARA_PCM_ADDR(&para) = PCM_ADDR+(0x4000*(i+1));
PCM_PARA_PCM_SIZE(&para) = PCM_SIZE;

pcm addr is in soundram and the ring too, just update the pcm addr when needed.
 
would someone know how to hack the sega sound driver to support up to 32 PCMs ?
in the sbl, it's easy to remove that limit but not in the sound driver. the other way would be to find a modified driver on a released game.

#define PCM_STREAM_MAX (8)

if (stream_no < 0 || stream_no > 7)
 
Last edited:
So you just send the data to audio RAM and simply make sure you have the right address?
Have you ever tried it with SGL functions directly, or do you need to use SBL functions?
As far as I know SGL sends the pcm data from work RAM to the audio RAM pcm buffer area during v-blank using the SCU DMA, so I'm not sure if it would create issues (since I'm using Jo Engine functions for audio, I would need to modify them or write my own, which is why I ask first instead of simply trying it right away).
Thanks again!

i'd say yes, see that :

#define PCM_ADDR ((void*)0x25a20000)

PCM_PARA_WORK(&para) = (struct PcmWork *)&g_movie_work;
PCM_PARA_RING_ADDR(&para) = (Sint8 *)PCM_ADDR+0x40000+(0x4000*(i+1));
PCM_PARA_RING_SIZE(&para) = RING_BUF_SIZE;
PCM_PARA_PCM_ADDR(&para) = PCM_ADDR+(0x4000*(i+1));
PCM_PARA_PCM_SIZE(&para) = PCM_SIZE;

pcm addr is in soundram and the ring too, just update the pcm addr when needed.
 
If you want to use Sega's sound driver, wouldn't you include your sounds in the tone data, and then either trigger sequences or send MIDI commands to play them?
 
If you want to use Sega's sound driver, wouldn't you include your sounds in the tone data, and then either trigger sequences or send MIDI commands to play them?
do you mean you can play pcm as a sequence ? or thanks to a midi command ? i'm not familiar with midi and sequences, i just play pcm from memory.
 
The tone definition ("voice") includes waveform data. Play notes using that tone, and the waveform will play. The sound driver includes commands for triggering sequences and for receiving direct MIDI messages. A sequence is basically a MIDI message stream, converted into a more compact format.

However if you're not using sequenced music, there's no real point in using the Sega driver either. And if you do want to use it, you run into the usual tool problems.
 
  • Like
Reactions: vbt
The tone definition ("voice") includes waveform data. Play notes using that tone, and the waveform will play.
maybe i'll do that, it seems easier than playing pcms, i got the sega sound tools working, i can try.
actually, i've merged all sfx into one single file.
if (size_write_total > st->pcm_bsize) {
// _VTV_PRINTF("\n\nmissed");
st->cnt_load_miss++;
// VTV_PRINTF((VTV_s, "P:LMis %d\n buf%X < writ%X\n",
// st->cnt_load_miss, st->pcm_bsize, size_write_total));
// VTV_PRINTF((VTV_s, " r%X w%X\n",
// (st)->ring_read_offset, (st)->ring_write_offset));
}
The sound driver includes commands for triggering sequences and for receiving direct MIDI messages. A sequence is basically a MIDI message stream, converted into a more compact format.
[/QUOTE]
yes but i heard that vgm/wav conversion to midi will not give a good result.
However if you're not using sequenced music, there's no real point in using the Sega driver either. And if you do want to use it, you run into the usual tool problems.
what's the alternative of the sega driver to play just pcms/wav??

my latest problem is now there, i started to debug the pcm lib, when i loose pcm streaming, i reach this point :
if (size_write_total > st->pcm_bsize) {
// _VTV_PRINTF("\n\nmissed");
st->cnt_load_miss++;
// VTV_PRINTF((VTV_s, "P:LMis %d\n buf%X < writ%X\n",
// st->cnt_load_miss, st->pcm_bsize, size_write_total));
// VTV_PRINTF((VTV_s, " r%X w%X\n",
// (st)->ring_read_offset, (st)->ring_write_offset));
}
it's something like the pcm lib refuses to play sound when the write size is higher than the block size, i got 16400 VS 16384 :(
 
here is my sound map (no idea what to put there) :

unsigned char sound_map[]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x07, 0x4D, 0x8C, 0xFF, 0xFF };

here is my sound memory map :

blktiger_sound_map.png


if someone see something wrong or see something to improve, tell me :)
 
Last edited:
So you will use PCM if I understand correctly?

Is it complicated to convert audio to the tone data?
 
not really, there are multiple ways to do that, i use mainly RB_SaturnPCM.EXE (http://www.rockin-b.de/saturn-tools-pcm.html)
you can try also the sega tone editor, it needs aiff as file source, i didn't use it enough to make a tutorial :

View attachment 4540
I set up a Mac emulator and loaded the tone editor app, but it seems to have problems loading .aiff files. Did you manage to make it all work?
And is there any advantage to go that route instead of just using PCM?
Also, the RB Saturn PCM doesn't seem to work well for me, it doesn't change the samplerate and doesn't seem to modify anything even if I use the options.
The result being that the audio files are wasting way too much RAM.
 
I set up a Mac emulator and loaded the tone editor app, but it seems to have problems loading .aiff files. Did you manage to make it all work?
It seems to work but i didn't try yet to use the generated file.
I used Gold wave to create aiff and the tone editor took all of them :

upload_2018-4-1_22-21-27.png


And is there any advantage to go that route instead of just using PCM?
no ideai, i tried to use that tool because I had some troubles with PCM & PCM streaming.
Also, the RB Saturn PCM doesn't seem to work well for me, it doesn't change the samplerate and doesn't seem to modify anything even if I use the options.
In fact i convert files with goldwave (resample + save as signed PCM)
then I run the rb tool like this :
SaturnPCM 0 51.wav mono 16 7680
The result being that the audio files are wasting way too much RAM.
Yes actually I use low sample rate to reduce file size, i think the next step is to use the adpcm codec.
 
  • Like
Reactions: XL2
Back
Top