+Andrew Davie Posted December 24, 2022 Share Posted December 24, 2022 Can someone point me towards some documentation on CDFJ capability (and examples...?) for CDFJ audio streaming. Particularly the "3 channels" that I've seen alluded to. I have some decent "normal" music playing in my game (envelope-based) but would like to see how CDFJ/streaming could improve this. Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 1, 2023 Share Posted January 1, 2023 Hmm, apparently I'd neglected to "follow" the Harmony/Melody club, so was unaware of your request until today. That's been rectified. We have a simple music, and a simple speech demo, used for testing the CDFJ driver as we made changes to it. I'll track down the most current versions and post them later today. I also ported the music driver from Stay Frosty 2 to CDFJ for John to use in Mappy. It does on-the-fly manipulation of the waveforms to generate ADSR. I'll track that down and post it as well. 1 Link to comment Share on other sites More sharing options...
+Andrew Davie Posted January 1, 2023 Author Share Posted January 1, 2023 3 minutes ago, SpiceWare said: Hmm, apparently I'd neglected to "follow" the Harmony/Melody club, so was unaware of your request until today. That's been rectified. We have a simple music, and a simple speech demo, used for testing the CDFJ driver as we made changes to it. I'll track down the most current versions and post them later today. I also ported the music driver from Stay Frosty 2 to CDFJ for John to use in Mappy. It does on-the-fly manipulation of the waveforms to generate ADSR. I'll track that down and post it as well. TY. I have ADSR in my own effort, but it's not using streams; just 60Hz manipulation of AUDV from hardwired ADSR envelopes, using preset AUDC/AUDF. First time I've ever done anything music related, so I'm on a steep learning curve. It does a surprisingly "good" job of simulating different instruments, though, rudimentary as it is. I'll PM you the latest to have a listen to. I'm somewhat bad at audio stuff, as my ears are nowhere near even slightly capable of hearing this stuff properly. Link to comment Share on other sites More sharing options...
bithopper Posted January 1, 2023 Share Posted January 1, 2023 (edited) Would be interested in the demos, as well. And a music driver would be just fantastic! Edited January 1, 2023 by bithopper Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 2, 2023 Share Posted January 2, 2023 CDFJ music demo cdfj_music.zip When using Music Mode the CDFJ driver supports playing back 3 voice music similar to the music in Pitfall 2. Unlike Pitfall 2's square waves only, CDFJ supports custom waveforms for a wider variety of sounds. Examples of this can be heard in Stay Frosty 2 and Mappy. Note: while SF2 uses the DPC+ driver, the ARM enhanced audio is basically the same as when using the CDFJ driver. The music only uses TIA's voice 0, voice 1 is available for your game's sound effects. In your 6507 code Set the mode to music update AUDV0 once per scanline call your ARM routines with Audio Interrupt turned on In your ARM code: Copy the waveforms from ROM into Display Data RAM call setWaveform() for each voice call setNote() for each voice 6507 code Set the mode to music When updating SETMODE make sure to use the AUDIOMUSIC constant: ldx #AUDIOMUSIC|FASTON stx SETMODE update AUDV0 once per scanline Read from AMPLITUDE and update AUDV0 once per scanline. For best audio quality do the update on the same cycle on every scanline, though this is not always possible. lda #AMPLITUDE sta AUDV0 NOTE: lda #AMPLITUDE requires SETMODE to have been set with FASTON constant. WARNING: Do NOT do this, you cannot "read ahead" from AMPLITUDE lda #AMPLITUDE ... any other 6507 code sta AUDV0 call your ARM routines with Audio Interrupt turned on When calling your ARM routines you will want to turn on the Audio Interrupt so the updates to AUDV0 will still occur about once per scanline. ldx #$FE ; Run ARM code with digital audio interrupt stx CALLFN ; Call Function The $FE tells CALLFN to trigger an ARM interrupt about once per scanline. The interrupt routine will calculate the current audio value, then output this sequence to the 6507's bus: LDX #value STX AUDV0 NOP And yes, this means the value in the 6507's X register will no longer be $FE after stx CALLFN has finished executing. NOTE: Using the audio interrupt will cause about a 10% hit in performance for your C code. ARM code Copy the waveforms from ROM into Display Data RAM For CDFJ driver performance reasons the waveforms must be located in RAM. The waveforms also need to be aligned on 32 byte boundaries. Search for "Waveform Tables" in cdf1_music.asm for more info and example waveforms. call setWaveform() for each voice C function setWaveform(voice, waveform), located in defines_cdfj.h, is used to set the waveform buffer used by each voice. voice = 0 - 2 waveform = which 32 byte waveform buffer. Basically the address offset into Display Data / 32. call setNote() for each voice C function setNote(voice, frequency), located in defines_cdfj.h, is used to set the frequency of each voice. voice = 0 - 2 frequency = frequency of the note. Use getPitch(note) , located in defines_cdfj.h, to calculate the frequency. note = 1-88 where 1 = A0 and 88 = C7 While the waveforms default to 32 bytes in size, you can change that using setWaveSize(voice, size), also located in defines_cdfj.h. I don't believe anybody has used this feature yet. 1 Link to comment Share on other sites More sharing options...
bithopper Posted January 2, 2023 Share Posted January 2, 2023 (edited) Thanks a million, Darrell, for this perfect starter pack. I feel obliged now to integrate it into my WIP. (...ok, lets begin with finding some extra cycles at a steady scan line position for each kernel line 😱) Edited January 2, 2023 by bithopper 1 Link to comment Share on other sites More sharing options...
bithopper Posted January 2, 2023 Share Posted January 2, 2023 (edited) Couldn't resist playing around with your danube song ... some experiment with dynamic wave forms for the lead voice. cdf1_music.bin Edited January 2, 2023 by bithopper Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 2, 2023 Share Posted January 2, 2023 31 minutes ago, bithopper said: Couldn't resist playing around with your danube song ... Actually @cd-w's song. He also used it when experimenting with the DPC's music abilities back in 2010: I also did a DPC experiment around the same time frame, though mine was with graphics: Our experiments with the Harmony's support for DPC lead to the creation of DPC+, and eventually CDFJ. Quote some experiment with dynamic wave forms for the lead voice. Fun! Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 2, 2023 Share Posted January 2, 2023 CDFJ speech demo (sample playback) cdfj_speech.zip When using Sample Mode the CDFJ driver supports playing back digital audio samples. Examples of this can be heard in Draconian. The samples only uses TIA's voice 0, voice 1 is available for your game's sound effects. If you're creative, you can still use voice 0 for sound effects whenever a sample is not playing. This also can be heard in Draconian. In your 6507 code Set the mode to sample update AUDV0 once per scanline call your ARM routines with Audio Interrupt turned on In your ARM code: Start sample Test for end of sample 6507 code Set the mode to sample When updating SETMODE make sure to use the AUDIOSAMPLE constant: ldx #AUDIOSAMPLE|FASTON stx SETMODE update AUDV0 once per scanline Read from AMPLITUDE and update AUDV0 once per scanline. For best audio quality do the update on the same cycle on every scanline, though this is not always possible. lda #AMPLITUDE sta AUDV0 NOTE: lda #AMPLITUDE requires SETMODE to have been set with FASTON constant. WARNING: Do NOT do this, you cannot "read ahead" from AMPLITUDE lda #AMPLITUDE ... any other 6507 code sta AUDV0 call your ARM routines with Audio Interrupt turned on When calling your ARM routines you will want to turn on the Audio Interrupt so the updates to AUDV0 will still occur about once per scanline. ldx #$FE ; Run ARM code with digital audio interrupt stx CALLFN ; Call Function The $FE tells CALLFN to trigger an ARM interrupt about once per scanline. The interrupt routine will extract the next sample value, then output this sequence to the 6507's bus: LDX #value STX AUDV0 NOP And yes, this means the value in the 6507's X register will no longer be $FE after stx CALLFN has finished executing. NOTE: Using the audio interrupt will cause about a 10% hit in performance for your C code. ARM code Start sample To start a sample reset the sample to the beginning, set the playback rate, and set the pointer to the sample's position. resetWave(0); setNote(0, rate); setNote(1, 0); setNote(2, 0); setSamplePtr(sample); Stop playback at end of sample Retrieve getWavePtr(0) to get the current playback position of the sample. Once end has been reached then stop playback (or start a new sample). if (sample_size > getWavePtr(0) >> 21) { // if sample has been fully played stop playback setNote(0, 0); resetWave(0); } Sample info Samples are 4 bit values, which are packed 2 per byte. Upper nybble of the byte is played back before the lower nybble. Max size of the packed sample data is 2K - which is 4096 sample values when the bytes are split into nybbles for playback. This C utility will convert a raw 8-bit audio file to the packed format. A raw file means there's no header information in the file, just digital samples. raw_to_dpc.c I used SOX to create raw 8-bit audio files. Link to comment Share on other sites More sharing options...
+SpiceWare Posted January 4, 2023 Share Posted January 4, 2023 I've tracked down the Stay Frosty 2 music driver I ported for John for Mappy. It's using an old version of the CDF driver, so I'll need to update it to CDFJ before posting it. On 1/1/2023 at 6:20 PM, SpiceWare said: Using the audio interrupt will cause about a 10% hit in performance for your C code. In regards to this, the performance hit is less than 10%. Your custom ARM code is idled once per scanline for this sequence of 6507 opcodes: 0-2 cycles waiting for the currently executing NOP to finish 2 cycles for LDX #value 3 cycles for STX AUDV0 0 cycles for NOP - custom ARM code resumes after putting this NOP on the bus For 5 - 7 cycles of run time per scanline, which is 6.6% - 9.2%, or a 7.9% performance hit on average. There's also a slight amount of time spent calculating the audio value, but its minuscule in comparison to the time it takes the 6507 to run those opcodes, so we could say about an 8% hit on average. 1 Link to comment Share on other sites More sharing options...
Recommended Posts