NESDev and Strangulation Records messageboards
Forum Index | FAQ | New User | Login | Search

Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode


SubjectSound Question new  
Posted byLaughy
Posted on7/29/03 6:16 PM
From IP64.161.57.25  



Please tell me if I have this right in regards to a 44.1khz sound wave.

I know the value written to the 11bit wavelength is a count-down timer clocked by the cpu cycle, and that it needs to clock 16 times before the wave is 'done'. Depending on the duty cycle, only part of this wave is actully high.

If a game writes 1152 to the 11bit wavelength, with a duty cycle of 2/14, then I would write "1"s to a sound buffer until (1152 * 16) / 7 cpu cycles had passed, and then write "0"s from then on? That would be 2633 cpu cycles, or about 1.47 ms, which is approximately 65 "1s" written compared to 455 "0s" written. This doesn't seem right, so could someone help me out? Thanks.




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/29/03 7:28 PM
From IP66.127.105.177  



With a wavelength of 1152 and a duty cycle of 2/14, you write the positive portion of the wave for -> 1152 * 2 cycles, and the negative portion for 1152 * 14 cycles. At 44100 Hz, that calculates to approx. 56.77 positive, 397.39 negative.

To get those numbers... take the apu frequency (1789772.7272) and divide by your output frequency (in this case 44100). 1789772.7272 / 44100 = 40.5844... that number is how many cycles are executed before you output another sample to your output buffer. So for the positive portion 1152 * 2 / 40.5844 = 56.77, and for the negative portion: 1152 * 14 / 40.5844 = 397.39

Hope that makes sense =P




SubjectRe: Sound Question new  
Posted byLaughy
Posted on7/29/03 8:11 PM
From IP64.161.57.25  



Thanks, it does, however I'm trying to figure out how decimals would work in this setting. I need to write one sample per 40.58444 cpu cycles...should I just write one at 41? Wait till 1152 has completed twice and write 57 (or 56?). I guess one shouldn't matter THAT much.

Thanks though, looks like we helped each other :)




SubjectRe: Sound Question  
Posted byLaughy
Posted on7/29/03 8:36 PM
From IP64.161.57.25  



What you said produces sound that matches frequency change, but not really the frequency. It sounds much too low. I believe the actual wavelength is supposed to be about 31 "1"s written and 224 "0"s.




SubjectRe: Sound Question new  
Posted byLaughy
Posted on7/29/03 8:55 PM
From IP64.161.57.25  



which are CONSEQUENTLY both 1.77x less than our calculations! o_O




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/29/03 9:03 PM
From IP66.127.105.177  



It seems like it would be tricky. I'm in the area of making NSF players... not full emus... so I don't have to deal with as precise of timing as you might have to.

All I can say is you definatly -SHOULDN'T- round off to the nearest whole number... as that will throw notes off key (especially notes with lower wavelengths)

Anyway... how I have my player running... is I keep track of how many cycles are needed per sample (as a floating point variable). Then I keep another floating point var as a sort of counter. The counter is decreased by the number of CPU cycles executed... when the counter goes under 0, a new sample is generated, and the counter is incrimented by the CyclesPerSample variable.

Hard to explain... so here's sample code as a description... hope you know C/C++

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


float fTicksPerSample; //number of cpu cycles between generated samples (40.5844)
float fSampleCounter = fTicksPerSample; //the counter

void DoAPUTicks( int ticks ) //ticks is the number of cycles to do
{
  int doticks;

  while(ticks > 0)
  {
    // make it so we only do one sample at a time
    doticks = (int)fSampleCounter + 1;
    if(doticks > ticks) doticks = ticks;

    // in my player, I clock other stuff here, like the frame counter


    // here... clock all the sound channels 'doticks' cycles

    fSampleCounter -= ticks;
    if(fSampleCounter <= 0)
    {
      fSampleCounter += fTicksPerSample;
      //add another sample to the sound buffer
    }
  }
}



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

hope that kind of makes sense. That's similar to how I do it and it's peachy. If you round off though, it WILL go off key... I tried it before.




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/29/03 9:05 PM
From IP66.127.105.177  



whoops... add:

ticks -= doticks;


before the while loops closes or you'll have an infinite loop ^_^


Ugh... and:

fSampleCounter -= ticks;

should be:
fSampleCounter -= doticks;


Sorry about all the mistakes... but hopefully you get the jist of it.




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/29/03 9:09 PM
From IP66.127.105.177  



I dunno... Unless I did some math wrong.. that should be right.




SubjectRe: Sound Question new  
Posted byLaughy
Posted on7/29/03 10:28 PM
From IP64.161.57.25  



No, I don't see how your function could work, unless every time you write to the buffer you write about 28 buffer values or so. Your function creates one sample every 1153 cpu cycles, but by the time we reach 1789 cpu cyles the 44.1khz wave requires we have 44 samples already in our buffer, unless you have a differenct scheme of sending ticks to the function. Check out my code (which is written in delphi, but you'll get it):

http://www.laughy.net/Square.txt

This writes out 28 or so bytes per "sample" that the APU would send out. Thus the 1153 square wave is consisted of 16 * 28 or 448 bytes. For a 2/14 duty cycle, About 58 of those bytes should be 1s and the other 390 0s. We have already acknowledged this, and the code outputs this, however the sound isn't slightly off, it's OFF. Other emulators spit out 31 and 220 for the 0 and 1 phases respectively, which is 1.77x smaller each than ours.

:(




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/30/03 00:05 AM
From IP66.127.105.177  



I forgot that the wavelength is that value plus 1. Sorry about that ^_^. So yeah.. my numbers are a little off

But aside from that... I see nothing wrong with the formula.

After double-checking the numbers again.. I came up with the same answer:

1789772.7272 (cycles per second)
44100 (samples per second)
1789772.7272 / 44100 = 40.5844 (cycles per sample)

1153 (cycles per duty cycle generator clock)
2 (positive sections in duty cycle)
14 (negative sections in duty cycle)
1153 * 2 = 2306 (cycles per positive section)
1153 * 14 = 16142 (cycles per negative section)

2306 / 40.5844 = 56.8199 (samples per positive section)
16142 / 40.5844 = 397.7390 (samples per negative section)



I'm really sure that's right. That's how I do it and there have been no problems at all.




SubjectRe: Sound Question new  
Posted byLaughy
Posted on7/30/03 00:16 AM
From IP64.161.57.25  



Great then I guess I'm screwed :(




SubjectRe: Sound Question new  
Posted byLaughy
Posted on7/30/03 00:41 AM
From IP64.161.57.25  



OH NO I FIGURED IT OUT!
-_-
It's not supposed to be 1152. The problem was I was shifting my bits that were written to 4003 one too many! NOOOOOOOOOOOO. It SHOULD be 640!!

640 / 40.58 = 15.8 * 2 is about 32
640 / 40.58 = 15.8 * 14 is about 221

I quit programming. It's going to give me a heart attack.

Thanks for all your help. :)




SubjectRe: Sound Question new  
Posted byDisch
Posted on7/30/03 01:48 AM
From IP66.127.105.177  



Don't be discouraged by one small bug ;). At least you figured it out ;)

Anyway... I'm glad I could be of some help. Best of luck to you with your projects ^_^




Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode
Jump to

Memblers' homepage             Contact Me

Forums powered by WWWThreads Demo