Fragmare Posted March 8, 2021 Share Posted March 8, 2021 Hey guys, I'm not a programmer, but do a lot of work with Atari chiptune & sound design, and I had a question or two about the difference in pulse frequencies between the original Activision DPC chip from Pitfall II and the newer DPC+ chip in the Harmony cartridge... I've done some tests with sound output from dpctuner.bin, and as we all know, the original DPC has 256 frequencies (really only 224, as 224-255 seem to all be exactly the same)... however, I've noticed only a select few of those frequencies are "pure". The rest seem to be interpolated, microtonal approximations of other "in-between" frequencies. Of which, about ~50 or so line up fairly well with actual note frequencies, when making a note table. My questions are... Does the DPC+ offer better tuning and more pure frequencies than the regular DPC? If so, is there a ROM file out there that showcases all the frequencies of the DPC+, like dpctuner.bin does for the normal DPC? Also, how do either of these chips handle volume when downmixing their 3 channels into a single TIA channel? Do they have their 3 channels pre-set to a volume level that will never exceed the TIA's 4-bit volume register, even when all 3 are combined? Or do they simply mix all 3 channels, and let the TIA's 4-bit volume register clip off any excess that might exceed max volume? Any insight or advice would be appreciated Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 8, 2021 Share Posted March 8, 2021 After we created DPC+ I posted a demo here where you'll find the frequency table we used: DPC_frequencies.h It's set up for 256 values, though we only defined 89 of them (0 which is silent, and 1-88 which are A0-C8). The values are included as part of your project, so you can change them to whatever values you wish. They are also copied into RAM for performance reasons. If the DPC+ project is using ARM code then the table is cut in half to 128 values and the freed up 512 bytes are reallocated for the C variable and stack space. Since they are in RAM they can be redefined on the fly. For Stay Frosty 2 I needed to free up more RAM for the C variables and stack, so I reduced the table to just 6 frequency values (0-5), which are calculated on the fly as the music plays by using this data table and function const unsigned int pitches[12] = { 476196134, // C7s 77 504512230, // D7 78 534512088, // D7s 79 566295831, // E7 80 599969533, // F7 81 635645578, // F7s 82 673443031, // G7 83 713488038, // G7s 84 755914244, // A7 85 800863244, // A7s 86 848485051, // B7 87 898938597 // C8 88 }; int get_pitch(int note) { // on the fly frequency calculations. Saves from having to store // 88 values in both ROM and RAM. // note will be 1-88. 1=A0, 88=c8 int scale; scale = 0; while (note < 77) { scale++; note+=12; } return (pitches[note-77]) >> scale; } 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 8, 2021 Share Posted March 8, 2021 There's one other difference as well. With DPC the waveforms are always square waves. In DPC+ you get to define them, I used the following waveform definitions in the DPC+ demo. Values range from 0-5 (except for noise) as when DPC+ add the waveforms for the 3 voices together the value should be between 0-15 to sound correct. SOUND_OFF = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 align 32 SINE_WAVE = (* & $1fff)/32 .byte 3,3,3,4,4,5,5,5 .byte 5,5,5,5,4,4,3,3 .byte 3,2,2,1,1,0,0,0 .byte 0,0,0,0,1,1,2,2 align 32 TRIANGLE_WAVE = (* & $1fff)/32 .byte 0,0,1,1,1,2,2,2 .byte 3,3,3,4,4,4,5,5 .byte 5,5,4,4,4,3,3,3 .byte 2,2,2,1,1,1,0,0 align 32 SAWTOOTH_WAVE = (* & $1fff)/32 .byte 0,0,0,0,1,1,1,1 .byte 1,1,2,2,2,2,2,2 .byte 3,3,3,3,3,3,4,4 .byte 4,4,4,4,5,5,5,5 align 32 SQUARE_WAVE_VOL5 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 5,5,5,5,5,5,5,5 .byte 5,5,5,5,5,5,5,5 align 32 SQUARE_WAVE_VOL4 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 4,4,4,4,4,4,4,4 .byte 4,4,4,4,4,4,4,4 align 32 SQUARE_WAVE_VOL3 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 3,3,3,3,3,3,3,3 .byte 3,3,3,3,3,3,3,3 align 32 NOISE_WAVE = (* & $1fff)/32 .byte 7, 1, 9,10, 2, 8, 8,14 .byte 3,13, 8, 5,12, 2, 3, 7 .byte 7, 1, 8, 4,15, 1,13, 5 .byte 8, 5,11, 6, 8, 7, 9, 2 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 8, 2021 Share Posted March 8, 2021 Like the frequencies, the waveforms end up in RAM for performance reasons. As such you can manipulate them on the fly. For Stay Frosty 2 I used these definitions: SOUND_OFF = (* & $1fff)/32 ; need this for no-music/2 sound effect .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 SQUARE_255: ; wave 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 255,255,255,255,255,255,255,255 .byte 255,255,255,255,255,255,255,255 .byte 0, 0, 0, 0, 0, 0, 0, 0 SAWTOOTH_255: ; wave 1 .byte 7, 15, 23, 31, 39, 47, 55, 63 .byte 71, 79, 87, 95,103,111,119,127 .byte 135,143,151,159,167,175,183,191 .byte 199,207,215,223,231,239,247,255 SINE_255: ; wave 2 .byte 1, 3, 11, 22, 38, 57, 79,103 .byte 128,153,177,199,218,234,245,253 .byte 255,253,245,234,218,199,177,153 .byte 128,103, 79, 57, 38, 22, 11, 3 SINE_SINE_255: ; wave 3 .byte 0, 8, 30, 64,105,148,188,221 .byte 243,253,250,238,219,198,180,167 .byte 162,167,180,198,219,238,250,253 .byte 243,221,188,148,105, 64, 30, 8 CLARINET_WAVE: ; wave 4 .byte 111,171,221,251,255,237,205,173 .byte 151,146,158,180,202,213,205,177 .byte 135, 88, 50, 28, 26, 41, 65, 86 .byte 95, 86, 63, 32, 8, 0, 15, 55 OBOE_WAVE: ; wave 5 .byte 172,202,233,255,255,230,189,148 .byte 121,110,107,106,107,116,138,167 .byte 187,186,161,123, 90, 70, 62, 52 .byte 35, 13, 0, 7, 35, 74,113,144 BANJO_WAVE: ; wave 6 .byte 127,207,254,255,223,183,156,143 .byte 132,117, 99, 90, 98,118,135,138 .byte 127,117,119,137,157,164,156,138 .byte 122,112, 99, 71, 32, 0, 0, 47 you'll note those are using 0-255. Stay Frosty 2 was written to merge waveforms together on the fly to create additional instrument sounds. The routine that does it will reduce the merged value to 0-VOLUME where VOLUME is the current voice volume of 0-5: for(j=0;j<32;j++) WAVEFORM_BUFFER[dest+j] = (volume * (WAVEFORM_DEFINITIONS[wave+j] + WAVEFORM_DEFINITIONS[wave2+j])) >> 9; Quote Link to comment Share on other sites More sharing options...
Fragmare Posted March 12, 2021 Author Share Posted March 12, 2021 On 3/8/2021 at 1:37 PM, SpiceWare said: After we created DPC+ I posted a demo here where you'll find the frequency table we used: DPC_frequencies.h 4.84 kB · 4 downloads It's set up for 256 values, though we only defined 89 of them (0 which is silent, and 1-88 which are A0-C8). The values are included as part of your project, so you can change them to whatever values you wish. They are also copied into RAM for performance reasons. If the DPC+ project is using ARM code then the table is cut in half to 128 values and the freed up 512 bytes are reallocated for the C variable and stack space. Since they are in RAM they can be redefined on the fly. For Stay Frosty 2 I needed to free up more RAM for the C variables and stack, so I reduced the table to just 6 frequency values (0-5), which are calculated on the fly as the music plays by using this data table and function Interesting! This actually does help a bit! So each of the three DPC+ channels can have volume ranging from 0-5? Not just 0 *or* 5? If so, this, in and of itself, is a HUGE advantage over the regular DPC which has no volume control whatsoever. This means you can potentially create enveloped instruments that sound MUCH better than they would on regular DPC. The ability to create rudimentary wavetables is also great! Especially for Namco arcade conversions where the original arcade sound hardware was wavetable based in the first place. I did want to ask for clarification about something regarding the DPC+ frequencies, though... Most old PSG chips have their available frequencies defined by the hardware itself, using pitch dividers. Usually, these will be arranged in a sort of gradient, where the frequencies are bunched up and closer together on the lower, bassy end and spaced further apart the higher up the frequency scale you go. You then must define a note table that uses only the hardware defined frequencies available. This can sometimes lead to tuning issues, depending on the number of hardware defined frequencies that are available (such as with the TIA, or to lesser extent, the original DPC) You're saying that the DPC+ note table is user defined, and can contain up to 256 entries (128 if ARM is in use). My question is this... must these 128 or 256 user defined note table entries also adhere to some sort of master frequency table defined by the DPC+ hardware itself, like older PSG chips? Or is it one of those things where the hardware defined frequencies of the DPC+ are so ridiculously numerous that you can essentially get perfect or near perfect tuning, if you want? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 12, 2021 Share Posted March 12, 2021 3 hours ago, Fragmare said: So each of the three DPC+ channels can have volume ranging from 0-5? Not just 0 *or* 5? correct - you could even do something like: channel 0 volume 0-7 channel 1 volume 0-4 channel 2 volume 0-4 or channel 0 volume 0-6 channel 1 volume 0-5 channel 2 volume 0-4 all that matters is the sum of the max volumes does not exceed 15. By changing the volume on the fly you can implement ADSR. I did that in Stay Frosty 2 using these ADSR definitions: ADSR_Data: .byte 2,3,4,5,6,6,6,6 ; ADSR 0 .byte 5,5,5,5,4,4,4,4 .byte 3,3,3,3,2,2,2,2 .byte 2,2,2,2,2,2,2,2 .byte 2,2,3,3,4,4,5,5 ; ADSR 1 .byte 6,6,6,6,6,6,6,6 .byte 6,6,6,6,6,6,6,6 .byte 6,6,6,6,6,6,6,6 .byte 2,3,4,5,6,6,6,6 ; ADSR 2 .byte 5,5,5,5,5,5,5,5 .byte 4,4,4,4,4,4,4,4 .byte 3,3,3,3,3,3,3,3 .byte 6,5,4,4,3,3,3,2 ; ADSR 3 supercat .byte 2,2,2,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 2,4,6,6,6,6,6,6 ; ADSR 4 iesposta .byte 6,6,6,6,6,6,6,6 .byte 6,6,6,6,6,6,6,6 .byte 6,6,6,6,6,6,6,6 The ADSR values range from 0-6 because the calculations are done using byte values, which range in value from 0-255. (255 * 6 )/ 256 = 5.9, which gets truncated to 5 because it's done using integer math. You can hear Stay Frosty 2's music here: or play it yourself using the ROM which is available here. The values in the frequency table are used in the DPC+ driver that runs on the ARM. I'm not familiar with the specifics, but am with the Stella implication: inline void CartridgeDPCPlus::updateMusicModeDataFetchers() { // Calculate the number of cycles since the last update uInt32 cycles = uInt32(mySystem->cycles() - myAudioCycles); myAudioCycles = mySystem->cycles(); // Calculate the number of DPC+ OSC clocks since the last update double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks; uInt32 wholeClocks = uInt32(clocks); myFractionalClocks = clocks - double(wholeClocks); // Let's update counters and flags of the music mode data fetchers if(wholeClocks > 0) for(int x = 0; x <= 2; ++x) myMusicCounters[x] += myMusicFrequencies[x] * wholeClocks; } ... case 0x05: // AMPLITUDE { // Update the music data fetchers (counter & flag) updateMusicModeDataFetchers(); // using myDisplayImage[] instead of myProgramImage[] because waveforms // can be modified during runtime. uInt32 i = myDisplayImage[(myMusicWaveforms[0] << 5) + (myMusicCounters[0] >> 27)] + myDisplayImage[(myMusicWaveforms[1] << 5) + (myMusicCounters[1] >> 27)] + myDisplayImage[(myMusicWaveforms[2] << 5) + (myMusicCounters[2] >> 27)]; result = uInt8(i); break; } myMusicCounter[x] is an array of 3 values, one for each voice. It's a 32 bit value to which myMusicFrequency[x] is added, which is one of the values in the 256 (or 128) entry frequency table. myMusicCounter is a 32 bit value - the topmost 5 bits define a value of 0-31, which is the current position in the waveform for that voice. After it hits 31 it will wrap back to 0, pointing at the start of the waveform. Quote Link to comment Share on other sites More sharing options...
Thomas Jentzsch Posted March 13, 2021 Share Posted March 13, 2021 19 hours ago, SpiceWare said: all that matters is the sum of the max volumes does not exceed 15. I am no musician, but we know that the TIA volumes are not linear (e.g. 15 is only twice as loud as 6). Which that means that the volumes of the different channels affect each other. Example (2 channels) Ch0: volume 0, Ch1: volume 5 -> Ch1 increases the total volume by 42.9% Ch0: volume 5, Ch1: volume 5 -> Ch1 increases the total volume by 32.1% (playing both at 6 would compensate the compression) Ch0: volume 10, Ch1: volume 5 -> Ch1 increases the total volume by 25.0% (not possible to compensate) Has anyone ever tried to compensate the volume compression? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted March 13, 2021 Share Posted March 13, 2021 2 hours ago, Thomas Jentzsch said: Has anyone ever tried to compensate the volume compression? Not that I'm aware of Quote Link to comment Share on other sites More sharing options...
atari2601 Posted June 3, 2021 Share Posted June 3, 2021 On 3/8/2021 at 8:48 PM, SpiceWare said: Like the frequencies, the waveforms end up in RAM for performance reasons. As such you can manipulate them on the fly. For Stay Frosty 2 I used these definitions: SOUND_OFF = (* & $1fff)/32 ; need this for no-music/2 sound effect .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 SQUARE_255: ; wave 0 .byte 0, 0, 0, 0, 0, 0, 0, 0 .byte 255,255,255,255,255,255,255,255 .byte 255,255,255,255,255,255,255,255 .byte 0, 0, 0, 0, 0, 0, 0, 0 SAWTOOTH_255: ; wave 1 .byte 7, 15, 23, 31, 39, 47, 55, 63 .byte 71, 79, 87, 95,103,111,119,127 .byte 135,143,151,159,167,175,183,191 .byte 199,207,215,223,231,239,247,255 SINE_255: ; wave 2 .byte 1, 3, 11, 22, 38, 57, 79,103 .byte 128,153,177,199,218,234,245,253 .byte 255,253,245,234,218,199,177,153 .byte 128,103, 79, 57, 38, 22, 11, 3 SINE_SINE_255: ; wave 3 .byte 0, 8, 30, 64,105,148,188,221 .byte 243,253,250,238,219,198,180,167 .byte 162,167,180,198,219,238,250,253 .byte 243,221,188,148,105, 64, 30, 8 CLARINET_WAVE: ; wave 4 .byte 111,171,221,251,255,237,205,173 .byte 151,146,158,180,202,213,205,177 .byte 135, 88, 50, 28, 26, 41, 65, 86 .byte 95, 86, 63, 32, 8, 0, 15, 55 OBOE_WAVE: ; wave 5 .byte 172,202,233,255,255,230,189,148 .byte 121,110,107,106,107,116,138,167 .byte 187,186,161,123, 90, 70, 62, 52 .byte 35, 13, 0, 7, 35, 74,113,144 BANJO_WAVE: ; wave 6 .byte 127,207,254,255,223,183,156,143 .byte 132,117, 99, 90, 98,118,135,138 .byte 127,117,119,137,157,164,156,138 .byte 122,112, 99, 71, 32, 0, 0, 47 you'll note those are using 0-255. Stay Frosty 2 was written to merge waveforms together on the fly to create additional instrument sounds. The routine that does it will reduce the merged value to 0-VOLUME where VOLUME is the current voice volume of 0-5: for(j=0;j<32;j++) WAVEFORM_BUFFER[dest+j] = (volume * (WAVEFORM_DEFINITIONS[wave+j] + WAVEFORM_DEFINITIONS[wave2+j])) >> 9; do these waves use the pcm2pwm program? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted June 3, 2021 Share Posted June 3, 2021 22 minutes ago, atari2601 said: do these waves use the pcm2pwm program? Never heard of pcm2pwm. I found this this: Quote It's output is intended for use with any 1-bit audio devices which require a simple playback routine and/or relatively high degree of compression. which says it's for 1-bit audio, DPC+ generates 4-bit digital audio. Quote Link to comment Share on other sites More sharing options...
atari2601 Posted June 3, 2021 Share Posted June 3, 2021 1 hour ago, SpiceWare said: Never heard of pcm2pwm. I found this this: which says it's for 1-bit audio, DPC+ generates 4-bit digital audio. Thats the program but what did you use to make the samples Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted June 3, 2021 Share Posted June 3, 2021 1 hour ago, atari2601 said: Thats the program but what did you use to make the samples Numerous people helped with the music in Stay Frosty 2. I don't recall specifics, this was back in 2012 or so, but some of the 32 byte waveforms were most likely created via the attached spreadsheets that I found in the source for SF2. You can open them using OpenOffice or LibreOffice. I used to use OpenOffice but switched to LibreOffice, I believe that was due to @Thomas Jentzsch's recommendation. waveforms.zip Quote Link to comment Share on other sites More sharing options...
stepho Posted June 4, 2021 Share Posted June 4, 2021 On 3/13/2021 at 10:12 PM, Thomas Jentzsch said: I am no musician, but we know that the TIA volumes are not linear (e.g. 15 is only twice as loud as 6). From work I have done on other embedded devices (not Atari), you can double the amplitude of the output waveform and it will not sound like double the volume to our ears. That's because the device is using linear values but our ears work on logarithm values. Most TV's with digital volume also suffer from this (ie volume 10% sounds okay but to double the perceived volume you need to go way up to 30% or more) For my device (which only needs simple buzzer-like sounds at various, fixed, frequencies), I set the amplitude according to the crude formula: amplitude = (vol^2)/100 where: volume is the desired volume 0..100 % amplitude is the amplitude of the output waveform 0..100 % Not truly logarithmic but parabolic is close enough. With this, the user can double the desired volume value and the perceived sound also appears to double. 1 Quote Link to comment Share on other sites More sharing options...
Fragmare Posted February 3, 2022 Author Share Posted February 3, 2022 On 3/8/2021 at 1:41 PM, SpiceWare said: There's one other difference as well. With DPC the waveforms are always square waves. In DPC+ you get to define them, I used the following waveform definitions in the DPC+ demo. Values range from 0-5 (except for noise) as when DPC+ add the waveforms for the 3 voices together the value should be between 0-15 to sound correct. SOUND_OFF = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 align 32 SINE_WAVE = (* & $1fff)/32 .byte 3,3,3,4,4,5,5,5 .byte 5,5,5,5,4,4,3,3 .byte 3,2,2,1,1,0,0,0 .byte 0,0,0,0,1,1,2,2 align 32 TRIANGLE_WAVE = (* & $1fff)/32 .byte 0,0,1,1,1,2,2,2 .byte 3,3,3,4,4,4,5,5 .byte 5,5,4,4,4,3,3,3 .byte 2,2,2,1,1,1,0,0 align 32 SAWTOOTH_WAVE = (* & $1fff)/32 .byte 0,0,0,0,1,1,1,1 .byte 1,1,2,2,2,2,2,2 .byte 3,3,3,3,3,3,4,4 .byte 4,4,4,4,5,5,5,5 align 32 SQUARE_WAVE_VOL5 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 5,5,5,5,5,5,5,5 .byte 5,5,5,5,5,5,5,5 align 32 SQUARE_WAVE_VOL4 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 4,4,4,4,4,4,4,4 .byte 4,4,4,4,4,4,4,4 align 32 SQUARE_WAVE_VOL3 = (* & $1fff)/32 .byte 0,0,0,0,0,0,0,0 .byte 0,0,0,0,0,0,0,0 .byte 3,3,3,3,3,3,3,3 .byte 3,3,3,3,3,3,3,3 align 32 NOISE_WAVE = (* & $1fff)/32 .byte 7, 1, 9,10, 2, 8, 8,14 .byte 3,13, 8, 5,12, 2, 3, 7 .byte 7, 1, 8, 4,15, 1,13, 5 .byte 8, 5,11, 6, 8, 7, 9, 2 So I see the wavetable size you are using appears to be 32x256. Is that the native wavetable size of the DPC+, then? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 3, 2022 Share Posted February 3, 2022 28 minutes ago, Fragmare said: So I see the wavetable size you are using appears to be 32x256. Is that the native wavetable size of the DPC+, then? You can have up to 128 waveforms defined in RAM. However that would use up the entire 4K of Display Data RAM, so you wouldn't be able to also use DPC+ datastreams for things like drawing graphics on the screen. Quote Link to comment Share on other sites More sharing options...
Fragmare Posted February 3, 2022 Author Share Posted February 3, 2022 16 minutes ago, SpiceWare said: You can have up to 128 waveforms defined in RAM. However that would use up the entire 4K of Display Data RAM, so you wouldn't be able to also use DPC+ datastreams for things like drawing graphics on the screen. 128 seems like waaaaay more wavetables than you'd ever need anyway. Like, really, from a chiptuner's perspective, that's more than enough to make some really nice sounds. Hmmm... if they are stored as 8-bit, I was thinking... you could possibly save RAM, if you wanted, by packing two 4-bit wavetables into a single 8-bit wavetable space. So wavetable #1 would occupy bit 0-3, and wavetable #2 would occupy 4-7. That would result in each waveform having a size of 32x16, which is still a nice size since the TIA volume register is 4-bit in the first place. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 3, 2022 Share Posted February 3, 2022 The ARM on the Harmony/Melody emulates everything about the cartridge - ROM, RAM, bankswitching, etc. @cd-wPerfect Harmony shows the main loop: 1) Wait for an address request from the Atari (A12 high). 2) Read address bus (A0-A11). 3) Fetch data from flash memory at the requested address (may perform bankswitching here). 4) Assert data on the data bus (D0-D7). 5) Wait until there is a change of address (A0-A12). 6) Repeat forever. For music, the value for AUDV0 is calculated during step 3. I doubt there's enough processing time for it to also deal with shifting waveform data from the upper nybble to the lower nybble. For CDFJ we added support for samples. Samples pack 2 values per byte. We have the processing time to unpack and shift the samples because it's not merging 3 waveforms on the fly. Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted February 3, 2022 Share Posted February 3, 2022 You could also store the wavetables in ROM and then load into RAM as needed. 1 Quote Link to comment Share on other sites More sharing options...
Fragmare Posted February 4, 2022 Author Share Posted February 4, 2022 3 hours ago, SpiceWare said: The ARM on the Harmony/Melody emulates everything about the cartridge - ROM, RAM, bankswitching, etc. @cd-wPerfect Harmony shows the main loop: For music, the value for AUDV0 is calculated during step 3. I doubt there's enough processing time for it to also deal with shifting waveform data from the upper nybble to the lower nybble. Ah, I see... I didn't know it would require a significant amount of CPU time to read that way. It just got me wondering because you said the DPC+ wavetables are stored as 8-bit, but the TIA's volume register is only 4-bit, which means the 8-bit amplitude values of the DPC+ wavetables would need to get rounded to the nearest 4-bit integer at some point anyway. It seemed like it was worth a shot for 2x the storage efficiency. Perhaps that kind of bitplane compression would still be viable for saving space in ROM, if not in RAM? I dunno, maybe... 2 hours ago, splendidnut said: You could also store the wavetables in ROM and then load into RAM as needed. Yea, that'd be optimal for having different musics in the game that have different wavetables! You'd only load up the wavetables you need into RAM while that particular song is playing. Most chiptune tracks I've made with wavetables on the PC-Engine and N163 thus far rarely if ever use more than 16 or so unique wavetables. I'd imagine with the 2600, as long as you had your basic waveforms (various pulse widths of square, a sawtooth, sine, triangle, and maybe a slap-bass wave) you'd be all set. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 4, 2022 Share Posted February 4, 2022 1 hour ago, Fragmare said: It just got me wondering because you said the DPC+ wavetables are stored as 8-bit, but the TIA's volume register is only 4-bit, which means the 8-bit amplitude values of the DPC+ wavetables would need to get rounded to the nearest 4-bit integer at some point anyway. Only the lower nybble of the byte is used when the wavetable is in RAM. I think you're remember this bit: On 3/8/2021 at 1:48 PM, SpiceWare said: you'll note those are using 0-255. Stay Frosty 2 was written to merge waveforms together on the fly to create additional instrument sounds. The routine that does it will reduce the merged value to 0-VOLUME where VOLUME is the current voice volume of 0-5: The 8-bit amplitudes used in Stay Frosty 2 are located in ROM. My custom C routines manipulate those values on the fly to implement ADSR, the results of which end up in the RAM version of the waveform that DPC+ plays back. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.