Page 1 of 2

Squeedo Synthesizer v2.0a

Posted: Sat Jul 10, 2010 7:45 pm
by Memblers
Just thought I'd share some results from my latest project, a rewrite and vast improvement to my Squeedo sound synth. The biggest functional difference is that I'm making the instrument format native to the synth, rather than everything being controlled by some registers the NES writes to. But I think that's great, since the instrument format (not including any waveform) currently is close to 200 bytes and sure to get larger (mostly because of all the envelopes). But it's all still user-controllable in real-time as it should be, these instruments will exist in RAM for each channel.

A big difference in the code is that the original version was written in PIC18F assembly, and this one is being written in C for portability. So the natural thing to do, before I make the NES board later, is to test out the synthesis as a PC program. :) I also used 2 cross-platform libraries, SDL and portmidi, so I guess it will work on mac/linux if it's ever any use. It's also my first actual program in C (other than hello world type stuff).

So, for now I've focused on wavetable synthesis like I did on the older version, and mostly the same in that regard. One new feature is being able to cross-fade between 2 different waveforms (using linear interpolation). Features like that are what call for all those envelopes, heheh.

So to get stuff going with it, I've gotten MIDI input working. So now I can use windows control panel to select the Squeedo synth as my MIDI device and hear it wherever I want. Fun stuff. :) I'm currently cheating with the polyphony, and only allowing one note per channel (unlike MIDI). So most MIDIs don't play right. I'm also totally ignoring the 'drum channel' until I improve the instrument format some more.

Here's a few example songs:
http://membler-industries.com/squeedo/S ... Carlos.mp3
played similar to the arcade game, but using 256 byte square waveform that I manually faded into a sawtooth wave as the song went on

http://membler-industries.com/squeedo/S ... et%202.mp3
this one uses a 256-byte waveform (same one for every channel) that is a sine wave blended with a sawtooth.

http://membler-industries.com/squeedo/S ... 0Child.mp3
this one is using a bunch of randomly assigned waveforms for each instrument. These are 32-byte waveforms. Everything is still using the same volume envelope though, so it's still pretty boring for now until I refine the instruments.

--------------------------------------------------------------
EDIT:
see all newer examples here http://membler-industries.com/squeedo/

--------------------------------------------------------------

EDIT (2) April 2013 :
I'm going to start linking to these directly. Note the following!
  • These are Standard MIDI Files played through the Squeedo synth using a wavetable-based General MIDI instrument set
  • I didn't make any of these MIDI files, I'll try to keep the source MIDI's here
  • There are not any kind of "finalized" version, mostly I recorded them as a log of my progress on the synth and MIDI instruments, i.e. the instruments were not 'tuned' for any particular song
  • These were recorded with the synth engine running on winxp and win7 PC, with Audacity through waveout, post-effect applied was normalization (some earlier ones were pre-amp'ed and clip, ugh)
  • Song credit corrections are welcome
These songs demonstrate some 256-byte wavetable-based General MIDI instruments, 8-bit sample playing (a timpani drum is the only sample), and the MIDI drum channel. The drum sounds currently use LFSR pseudo-noise only, or an alternate "aliased noise", used for cymbals. I'll add further edits and eventually bump this thread once other synthesis modes are better utilized.

Posted: Sun Jul 11, 2010 1:28 am
by Bregalad
Sound cool. So basically you have a MIDI synth in a pic, and send data to the NES via a port which is supposed to be copied to $4011, right ?
It sound N106-like to me.

Posted: Sun Jul 11, 2010 3:02 am
by Memblers
Yep, N106 is based on wavetable synthesis as well. I was inspired a lot by Konami's music for the SCC on the MSX, and stuff like the arcade version of Spy Hunter.

I used the IRQ to $4011 method like you said on the original Squeedo, and I still want to do that with this one too. But, I'm also thinking I will put a DAC on the cart that will require an audio mod for the NES (not like the PowerPak one, but 2 wires for audio in and out). I'm also wanting a stereo line-out connector on the cartridge as well.. I'd rather use that but I'll have to see how that will work into it.

There will be some memory on the cart that will be usable as wave memory. If the memory was used for nothing but that, you could have over 400kBytes of samples at once. That could play a lot of MODs, or sound similar to the SNES. When I get sample playing implemented I'm thinking I'll try grabbing a BRR sample decoder and try playing some of the SNES music MIDIs with the original samples, heheh.

Posted: Sun Jul 11, 2010 9:07 am
by Bregalad
That's whicked !!
A line-out on the cartridge would suck IMO it would force the user to use headphones, and prevent the use of the regular sound channels.

Other than this it's really exiting. If you implement true looping and non-looping samples (not just a fixed-length waveform) you'll get GBA-style sound (with PSG + wavetable channels). It's be only slightly worse than GBA because it's 7-bit instead of 8-bit.

Posted: Sun Jul 11, 2010 9:19 am
by koitsu
Whatever this thing is (Squeedo), it sounds neat (audibly). Can you explain what it is, Memblers? Sorry if that sounds like a stupid or ignorant question, but I couldn't find an answer on the forum here.

Posted: Sun Jul 11, 2010 12:15 pm
by tokumaru
My question is: can this be done at the same time as a complex game (i.e. not a single-screen puzzle) runs? Or is most of the CPU time taken?

Posted: Sun Jul 11, 2010 1:03 pm
by tepples
It depends on the mixer frequency.

All the synthesis is done on the Squeedo side. So the CPU has to do this:

Code: Select all

  /IRQ       ; 7
  pha        ; 3
  lda squeedo_sample_output  ; 4
  sta $4011  ; 4
  pla        ; 4
  rti        ; 7
If this ISR executes once every two scanlines (227 CPU cycles), a 29-cycle ISR takes about 1/8 of CPU time.

I just remembered $4011 is write-only. If the cart decodes $4011 to a read-only register, can the CPU see it? Because if so, the ISR would execute in only 18 cycles:

Code: Select all

  /IRQ       ; 7
  inc $4011  ; 4
  rti        ; 7

Posted: Sun Jul 11, 2010 1:56 pm
by Bregalad
1/8 of CPU time is not negligible, but largely acceptable. Also, this could be further decreased by decreasing the sampling rate (haha this makes it even more similar to the GBA to what I first thought).
A pair of lda/sta zeropage would be 1 cycle faster than pha/pla, too. Or even better, place the interrupt code in zero-page, and have the sta instructoin overwrite the lda before the RTI, to be 1 cycle even faster (so 2 cycles faster than your solution). Something like that :

Code: Select all

ZPage_IRQ
  sta _saveA+1
  lda Squeedo_Audio  ;Hopefully this read acknownledges the interrupt
  sta $4011
_saveA
  lda #$00
  rti
Tepples, your later idea is in fact incredibly clever, but you'd loose accuracy low bit doing that, because it would write two consecutive values. The question is, would this cause any distortion to the sound ? Well after thought, it's very very unlikely a 1-cycle error can give anything audible - so I guess it's really a good solution.

Posted: Sun Jul 11, 2010 2:09 pm
by blargg
Heh, I had the same idea as tepples. You wouldn't lose any accuracy either, because squeedo would give you back a value one less than the one to be written to $4011. You could also use LSR, and have Squeedo output 8-bit unsigned samples.

Posted: Sun Jul 11, 2010 2:38 pm
by tepples
blargg wrote:You could also use LSR, and have Squeedo output 8-bit unsigned samples.
I thought of that, but it would produce a slight click between the unmodified writeback and the modified writeback. It's probably imperceptible, but I went with INC anyway.

I don't know how to program PowerPak mappers, or I'd test this theory myself.

Posted: Sun Jul 11, 2010 6:50 pm
by Memblers
Wow, the INC $4011 idea is great. If you want 44khz sound like the MP3s (those are 16-bit though) then you would doing this about once per scanline, with that optimization freeing up well over 2000 CPU cycles per frame.

Today I got the MIDI polyphony working (using some wacky on-the-fly channel assignment / note-stealing stuff), using 24 channels so it's up the General MIDI standard. 4, 8, and 16 channels is more like I was thinking to use on the NES version, 24 channels is a bit much.

Bregalad: For the line-out I would suggest an adapter like this one (very cheap if you buy it at the right place). I think it also should be possible to pass through and mix the regular NES channels on the cart, but of course that still needs the aforementioned audio mod to the NES (or use a Famicom with a modded NES adapter for all these cases :D). It was also thinking it could be fun to hook the NES audio up to the PIC's ADC, and display the waveform while playing NSFs on the actual system, heheh.

koitsu: Back in 2004 or so I had started writing a sound synth to run on the NES, but realized I was quickly running out of CPU cycles and needed an IRQ, I was also designing a game that needed more than 8kB WRAM (and being able to save), so I set out to design a board that would have everything I needed. So with it I'm (ab)using an MCU and using it like a DSP, have FlashROM on board, lots of RAM.. Then since the MCU has all these hardware peripherals (especially the serial ports), I coded a small kind of API/BIOS thing so the NES can use the RS232/USB and stuff like that, right over the data bus. There are pictures of the various boards here, but that's all old stuff from 5 years ago and I've learned a lot since then, heheh. I've had a lot of help from kevtris too, on the original and this newer one with solving and optimizing some of the main design issues.

This new design is still in it's infancy though, there's not even a schematic yet, just a parts list and a pretty good idea of how it will all fit together. I'm trying not to get too freaked out about how much it will cost to have a batch produced, heheh.

tokumaru: There is the CPU cycle draining issue (the older Squeedo had to wait for the IRQ acknowledge to be handled, so it was possibly a little worse), but another issue that the using the IRQ for something else like a scanline timer would tie it up even more when checking the IRQ source. On the CHR-side at least, there is one thing that helps out - the CHR (and perhaps nametable) switching can be automated to happen at a specified time, so no interrupt is needed for that.

Posted: Mon Jul 12, 2010 2:11 am
by koitsu
Memblers wrote:koitsu: Back in 2004 or so I had started writing a sound synth to run on the NES, but realized I was quickly running out of CPU cycles and needed an IRQ, I was also designing a game that needed more than 8kB WRAM (and being able to save), so I set out to design a board that would have everything I needed. So with it I'm (ab)using an MCU and using it like a DSP, have FlashROM on board, lots of RAM.. Then since the MCU has all these hardware peripherals (especially the serial ports), I coded a small kind of API/BIOS thing so the NES can use the RS232/USB and stuff like that, right over the data bus. There are pictures of the various boards here, but that's all old stuff from 5 years ago and I've learned a lot since then, heheh. I've had a lot of help from kevtris too, on the original and this newer one with solving and optimizing some of the main design issues.

This new design is still in it's infancy though, there's not even a schematic yet, just a parts list and a pretty good idea of how it will all fit together. I'm trying not to get too freaked out about how much it will cost to have a batch produced, heheh.
You hardware guys blow my mind. You always make it look so easy... :-)

How exactly do you interface with the board though? What I mean is, how do you feed it sequence data? I'm guessing the RS232 or USB port is involved, but maybe not. MIDI port? *clueless*

Posted: Mon Jul 12, 2010 3:40 pm
by Memblers
koitsu wrote: How exactly do you interface with the board though? What I mean is, how do you feed it sequence data? I'm guessing the RS232 or USB port is involved, but maybe not. MIDI port? *clueless*
Actually, I do want to put MIDI input on this one. Right now that is what it's doing in the PC version (and using the popular "MIDI-Yoke" windows driver so I can redirect between MIDI ports). In this setup, it is only getting the notes commands and such as they happen.

The first code I started writing for the MIDI part was a General MIDI file parser. So you could just load and play any .mid file. But I was running into the problem of having to support (or carefully ignore) pretty much every MIDI feature imaginable before getting to the good stuff. So I went the easy way and used the 'portmidi' library to filter out stuff I didn't want yet. I am kind of hoping later to get that working properly, but I'm leaning more towards using a tracker and also hacking it into MCK. This reminds me too, I was thinking maybe I should get an NES sound emulator working in the PC version soon..

The other interface is the parallel port on the PIC, it's a really great peripheral. It improved a lot on the PIC32, now there is a FIFO (4 bytes, but that's better than none on the PIC18 - a big timing hazard). But it can just sit on the data bus, and has /RD, /WR, /CE. Since there is a DMA, kevtris and I were speculating that the NES CPU perhaps could jump to this register and execute entirely off of the PIC. That could be an interesting way to copy data (since loading with LDA #immediate is fast), or it could also make for some industrial-strength copy protection. Seems possible in theory, may have issues in reality though. It should be able to run 4 bytes of code at the minimum, I suppose. :)

Posted: Mon Sep 13, 2010 8:29 pm
by Memblers
I've added some more features to the synth, still needs a little fine-tuning (literally!) before I record some new songs though.

I've added support for 8-bit PCM samples. I tried some very basic linear interpolation, which makes it a little less noisy (but not much better). There's not a whole lot of memory for samples, but I might see how quickly I could load a sample out of external memory when an instrument change command is given. Right now, instruments are imported from .XI format (FastTracker 2). The fine-tune setting isn't implemented yet, though, so the samples have to tuned already.

I also made a phase distortion synthesis mode, this could sort-of emulate Casio keyboards from the 80's.
http://membler-industries.com/squeedo/S ... thesis.mp3

Next up should be the Yamaha "FM" phase modulation. I also need to add support for the MIDI drum channel, instead of ignoring it still.

All these different modes are able to play at the same time now, selectable for each channel.

Other sounds are here: http://membler-industries.com/squeedo/, not much to see yet though. I'll make a board soon, so I can hopefully get it running on the PIC32 soon.

Posted: Fri Dec 24, 2010 1:43 pm
by Memblers
I haven't worked on this again until just recently, but I fixed a major bug that was causing lots of distortion (when using the 32-byte waveforms). Now I can apply that distortion in a controlled way, heheh.

I've got some ideas of more stuff to post up, but I was curious if anyone has any song requests (game music or not) or specific MIDI files to hear with it. Right now I'm working on creating the default instrument settings for it.

edit: Only one new file has been uploaded so far.