Ok, I've been able to understand and mostly emulate just about everything in the NES....except the sound. Sound is my absolute weakest link in my Computer Science knowledge(along with networking) and I'm having the hardest time trying to find out how to play this stuff on a modern machine!

Now I could use that one sound emulator that I think blargg created, but I really feel that I should do this on my own as I think I'll have to learn how to deal with sound sooner or later.

I've been searching for days in how to emulate this stuff using Allegro, with no luck at all. Right now, I'm looking into OpenAl, but I don't think I should get my hopes up.

Tutorials on Allegro5's audio seems to be non existent except for the documentation, which only lists the functions and structs and very briefly what they do. Even if there was one, it would most likely be about loading sample files and not about manipulating the sound programmaticaly. So maybe I should look to another another library like OpenAl? Or perhaps there's something fundamental that I'm not getting here?

Now, from my incredibly limited understanding I believe I can produce the sound by producing these simple waves? Like the square wave. It looks pretty simple, but how do I produce this with a sound library? Can I produce a square wave using samples?

Ok, I used a stream object and kind of copied the stream method of ex_synth and I'm glad that I actually got a sound to come out that kind of sounds like a square wave, but testing it against other programs that produce square waves(including ex_synth) it sounds waaaay off. Most likely frequency related.

Wish I had the code with me, but I don't

But basically I have a class called Square Wave that just takes a wavelength(in the same range as the nes's square wave 1). Now, from my understanding you can get the frequency from wavelength from an equation that I can't remember right now... ( wavelength = (C / (16f) )-1; solve for f... I solved it yesterday but I can't do it again today for some reason >_<; oh and C == NES's CPU cycles per second)

Anyway, I barely have any idea what I need to do with the frequency. I'm fairly sure that I need to play wavelength samples frequency times in a span of a second, but I don't know how to do the algorithm for that in conjunction with Allegro's stream object and functions.

EDIT: Before I just had makeshift code from memory. Now it's the real code.

int GetWaveLength() {return WaveLength;} int GetFrequency() {return Frequency;} int GetDT() {return dt;}private: int WaveLength; int Frequency; // Can't find a place to use this with without // making it not work at all int dt; // or this};

In the main code I make an ALLEGRO_AUDIO_STREAM object that is made with al_create_audio_stream(), with one fragment, samples == the wavelength, frequency is 44100, depth is float32 and channel is CONF_2. Also, before that, allegro init, the audio add-on init and al_reserve_samples() are called...

then I call al_get_audio_stream_fragment() which is assigned to a pointer to a void called buffer and then it's looped until it doesn't equal zero. Then I call al_set_audio_stream_fragment() and that's basically what I did.

A sound DOES play and it does sound like a square wave, but at, say, a wavelength of 9, where it's supposed to sound very high....doesn't sound very high at all. and when the wavelength is 0x7FF(the max value accepted for nes's wavelength) it sounds...very little like what other programs produce(including emulators) at that same wavelength.

So, I'm stuck until I can find a solution to this...

I'm pretty sure it has to do with the frequency of SquareWave and the frequency that I put into the al_create_audio_stream function and I've experimented, but it just ends with worst results >_<.

if ((square1_negative=1) and (square1_enablesweep=1) and (square1_sweep>0) and (curstep<5)) Then square1_timer = square1_timer - (square1_timer Shr square1_shift) ElseIf ((curstep<5) And (square1_enablesweep=1) and (square1_sweep>0)) Then square1_timer = square1_timer + (square1_timer Shr square1_shift) End If if ((square2_negative=1) and (square2_enablesweep=1) and (square2_sweep>0) and (curstep<5)) Then square2_timer = square2_timer - (square2_timer Shr square2_shift) ElseIf ((curstep<5) and (square2_enablesweep=1) and (square2_sweep>0)) Then square2_timer = square2_timer + (square2_timer Shr square2_shift) End If End If

and then this is at the end of my 6502 opcode execution loop after each instruction:

Code:

If ((triangle_enable) And (triangle_timer<=(totalticks-lasttriangletick))) Then triangle_clock(): lasttriangletick = totalticksIf ((square1_enable) And (square1_length>0) And (square1_timer>=8) and (square1_timer<=(totalticks-lastsquare1tick))) Then square1_clock(): lastsquare1tick = totalticksIf ((square2_enable) And (square2_length>0) And (square2_timer>=8) And (square2_timer<=(totalticks-lastsquare2tick))) Then square2_clock(): lastsquare2tick = totalticksIf ((noise_enable) and (noise_length>0) and (noise_timer>=8) and (noise_timer<=(totalticks-lastnoisetick))) Then noise_clock(): lastnoisetick = totalticks

What is the point of posting all these images? I can understand doing it every once in a while to spice things up, but you're doing it quite a lot, and in sometimes inappropriate places (why put down a guy who shares his code?).

What is the point of posting all these images? I can understand doing it every once in a while to spice things up, but you're doing it quite a lot, and in sometimes inappropriate places (why put down a guy who shares his code?).

seriously... i'm trying to help show the guy how i did my sound emulation.

well, he was asking about allegro yeah but he also said he's not sure how to generate a square wave, etc using samples. he was wondering if allegro or another lib had a way to generate it. i was showing how you have to generate sound when emulating the NES APU, and all the variables involved in the waveform output.

Well, basically, I never could interface the Allegro' sound in my emulator "error-free". It's not an easy task and I even couldn't take the "risk" of trying Allegro 5.

Regarding the samples, well... as far as I know of it, you would need to generate 1 sample at every CPU clock cycle. That means a resample to the PC frequency. I add all the samples and divide by the number of updates. Using Allegro, the amount of samples is always the same; so, you would feed the buffer with, let's say, 2048 samples per sound sync.

the following may not be 100% accurate, but as i understand it, every APU channel has a countdown timer n and a new sample for that channel is generated every n CPU ticks.

at the same time the new channel samples are calculated, the variables for the channel are updated/stepped (like the position of the duty cycle step on the squares, and for the triangle it steps where it is in the 32-byte lookup table)

then every 1789773 divided by 240(on NTSC) clock ticks, it steps another counter. every 4 steps of that, the square sweep counters are decremented and all of the length counters are decremented. every 4 or 5 steps (depending on a value written to register $4017) that counter wraps back to zero.

every 1789773 divided by samplerate CPU ticks you'll want to mix together all the channels' sample values and there's your output sample to put in your final stream.

that's oversimplying the process, but that's basically how things would be done in an emulator.

i can't speak for getting allegro going, as i've always used SDL, and it's great. never had an issue with it.

Who is online

Users browsing this forum: No registered users and 3 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum