Jump to content
IGNORED

Sound frequency and downmixing differences? Activision DPC vs. Harmony DPC+


Fragmare

Recommended Posts

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  :)

Link to comment
Share on other sites

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;
}

 

  • Like 1
Link to comment
Share on other sites

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

 

 

Link to comment
Share on other sites

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;

 

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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? 

Link to comment
Share on other sites

  • 2 months later...
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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

  • 7 months later...
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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...