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

Previous ThreadView All ThreadsNext Thread*Show in Threaded Mode


SubjectEmulation Sound Quality new  
Posted byblargg
Posted on7/3/04 12:43 PM
From IP199.170.89.169  



I've completed Blip_Buffer, a small library to handle the basics of band-limited synthesis, useful for writing a sound chip emulator. There's also a page describing why band-limiting is necessary and how it can be done for simple waveforms (it's how Blip_Buffer works internally). There are a few mp3 samples comparing audio quality and demonstrating the adjustable low-pass and high-pass filtering that's built-in. I'm hoping that this information or library will help with emulation sound quality, as virtually all emulators I've looked at use less-than-optimal methods.

http://www.slack.net/~ant/nes-emu/






SubjectRe: Emulation Sound Quality new  
Posted byDrilian
Posted on7/7/04 7:50 PM
From IP64.132.82.61  



I'd like to use this in my emulator, since I don't think I'd ever be able to get my own sound routines to sound as good as this.

I succesfully built the apu_demo with Visual Studio 7.1, and I'm currently working on hooking it into DirectSound for realtime output.

I'll let you know how it goes :)






SubjectRe: Emulation Sound Quality new  
Posted bykoitsu
Posted on7/8/04 02:16 AM
From IP64.169.94.72  



One word: awesome. Awesome awesome awesome.

-- jdc


SubjectRe: Emulation Sound Quality new  
Posted byDrilian
Posted on7/8/04 3:35 PM
From IP64.132.82.61  



Okay, my DirectSound wrapping is a little bit sketchy, but I know how to fix it at least. Anyway, I've gotten it up and running in my emu (which should have its first incarnation be done in the next few weeks), and it sounds really, really good! Much better than the work I did on my own :)

Anyway, I have a few notes:
1. Your files, interestingly, contain only carriage returns (character 0x0D) and not newlines (0x0A). This wreaks havoc on MSVC, which looks for newlines. It chokes on the files (until I changed it in a hex editor). Ironically, MSVC's text editor displays them just fine.

2. Also, your code generates a boatload of warnings (mostly "conversion from TYPE1 to TYPE2, possible loss of data" warnings). It's not a problem, but I do so much like warning-free code :)

3. It would be nice if there was something that I could ping on every cycle or so to determine whether there's a frame or DMC irq waiting (Only one function is necessary - I only need like a "wants_irq(nes_time_t)" function, since $4015 will sort out which type it is for the program). I hacked a quick one in, but I'm always afraid that I've gotten something wrong when I modify code that I don't know very well :)

Other than those three things, everything is great! Thank you so much for making the handiest library EVER.


Josh






SubjectRe: Emulation Sound Quality new  
Posted bykoitsu
Posted on7/8/04 6:12 PM
From IP64.169.94.72  



CR-only is the sign of an Apple-based system.

Apple: CR
*IX: LF
DOS/Win32: CR+LF

The most historic example of incompatibility between environments there is -- and it still plagues us today. Absolutely amazing.

Solution: Use an unzipping application which will auto-convert text files from the host system type to the client system type. The *IX utility "unzip" has a flag for this: -a.

Best wishes.

-- jdc


SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/10/04 03:29 AM
From IP199.170.89.104  



Thanks for the note about carriage returns. I already use a little program to assemble the files from several locations before zipping, so I'll add this. I'm assuming Unix-style newlines are best.

I haven't figured out how to get along with "possible loss of data" warnings. I'll have to revisit the issue in more depth. I run into problems finding some benefit which outweighs their cost.

Argh, regarding the DMC and IRQ, I had just removed all that from the latest version of Nes_Snd_Emu, since it wasn't necessary for playing NSFs and the APU IRQ code wasn't completely working. I'll put it back in and post an update in a few days.

Other than those three things, everything is great! Thank you so much for making the handiest library EVER.

If you're writing a GameBoy emulator any time soon, I just spend the last two days writing a GameBoy sound emulator with almost identical design style as the NES sound emulator :) It started as an experiment with applying Blip_Buffer to gbsplay and ended up with a complete rewrite (and 30x performance increase).

These are my first library-releasing experiences so the feedback is useful.





SubjectRe: Emulation Sound Quality new  
Posted bykoitsu
Posted on7/10/04 04:16 AM
From IP64.169.94.72  



I'm __REALLY__ hoping once Drillian gets his DX-based implementation done, someone with Win32 knowledge will take up writing a tracker-like interface for music composition. A native Win32 port of NT2 would be a good start.

A tool like that would be revolutionary in the realm of NES development.

-- jdc


SubjectRe: Emulation Sound Quality new  
Posted byDisch
Posted on7/10/04 04:37 AM
From IP66.82.9.28  



As always, you're totally rocking blargg =)

Your sound samples always blow me away. I'm still having trouble with the Kid Icarus opening. The individual square channels play fine on the high notes, but when you play them both at once, you get that aliasing ghost note in there ever-so-subtley.

I'd probably use your library to solve it... but I'm kind of a nut about using my own code whenever possible ;P. Plus with all my weird oddball features I add it would be hard working with someone else's library (I had a hard enough time getting all my tweaks to work with the VRC7 code I took from FCEU).

I took a gander at your source but got lost. Hardcore C++ is difficult for me to follow... I'm more of a C/C++ hybrid guy (mostly do C based stuff... but with classes and other simple C++ concepts here and there).

I scanned your site and read the docs. Does your Blip Buffer library actually do that whole sine wav thing to make the squares? And I didn't really understand the Working with Differences part... I mean how would calculating the difference between output changes produce a different sound (or even use less CPU) than outputting the absolute value?

Anyway... blah blah. I'd like to get in touch with you sometime and pick your brain a bit.




SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/10/04 10:17 AM
From IP199.170.89.186  



I'm still having trouble with the Kid Icarus opening. The individual square channels play fine on the high notes, but when you play them both at once, you get that aliasing ghost note in there ever-so-subtley.

Oh if you knew how many years I have been working on making NES music on my PC :) I've been working on it since about 1992, and it was only in the last year that I found out about band-limited synthesis and it clicked, where I stopped thinking of it like antialiasing graphics where you do simple averaging with adjacent pixels. I added a section at the end of my band-limited synthesis tutorial http://www.slack.net/~ant/bl-synth/ about averaging (which comes out the same as linear interpolation) compared proper band-limiting.

I'd probably use your library to solve it... but I'm kind of a nut about using my own code whenever possible ;P.

Somehow I keep forgetting that the enjoyment for others is in understanding the material oneself and writing the code (even though that's why I enjoy it). If the point was just to benefit from it, one could just download an app and be done with it. I'd like to improve or expand the tutorial above enough so that it provides enough information for writing an actual implementation. Don't give in just yet! :)

Plus with all my weird oddball features I add it would be hard working with someone else's library (I had a hard enough time getting all my tweaks to work with the VRC7 code I took from FCEU).

This is valuable, since without different code bases new ideas are stifled and one is at home with one's own code. For example I still haven't found a workable way to handle the non-linear NES DAC behavior.

I scanned your site and read the docs. Does your Blip Buffer library actually do that whole sine wav thing to make the squares? And I didn't really understand the Working with Differences part... I mean how would calculating the difference between output changes produce a different sound (or even use less CPU) than outputting the absolute value?

As shown, a square wave of any frequency (width) can be approximated by one set of pre-computed transitions; the only notable aspect is that a transition is a ripply affair rather than a hard edge. Working with differences is *not* fundamentally necessary, it just makes it easier to handle the case where two transitions occur close together and their edge ripples overlap. It simplifies the interface, since Blip_Buffer doesn't need to know about how long the waveform stays constant after a transition. It comes out more efficient because the flat parts of the waveform don't need any action (consider adding 4 waveforms into a buffer where every sample has to be added versus just the samples around transitions).

Anyway... blah blah. I'd like to get in touch with you sometime and pick your brain a bit.

This would help improve the presentation too. I'll admit I'm not that great at documenting things clearly :)





SubjectRe: Win32 tracker new  
Posted byBloopaws
Posted on7/10/04 11:54 AM



Yes! Yes! I agree; DOS NT2 is powerful, but as it is even MML is more comfortable for me, so a windows port was my first thought. Unfortunately, I'm easily sidetracked (partly why I've been lurking so much--I don't want to disappoint people).

Still, if anyone wants to pick it up themselves, I'd be glad to give you my meager notes. So far I've documented most of the .NED (and assembled .NSF) formats, but not the specifics of the player itself. Otherwise, I'll consider giving it another try. I've already gotten Disch's APU DLL to play NSFs, and it would be easy enough to rip out my emulation and play music from the PC side.

And speaking of dream tools.. I'd LOVE to see a sequencer with a programmable/plugin backend, so the same program can handle several platforms, NES being just one of them. With new plugins we could experiment with more elaborate/more size-efficient music formats, or better, implement special things like blargg's excellent sawtooth hack... I'm not sure how such an editor would work, though, since it would have to be generic enough to have a flexible backend but specific enough to have a useful UI.



-- Draci


SubjectRe: Emulation Sound Quality new  
Posted byDisch
Posted on7/10/04 10:29 PM
From IP66.82.9.46  



where I stopped thinking of it like antialiasing graphics where you do simple averaging with adjacent pixels

That seems to be the method most used... since it's probably the most obvious way to go about it. That's what I've been doing for a while too... and it works for most things... but like I pointed out earlier... with Kid Icarus it just doesn't cut it.

Somehow I keep forgetting that the enjoyment for others is in understanding the material oneself and writing the code (even though that's why I enjoy it).

Haha... word. I've always been a fan of reinventing the wheel so that it works in a way I want it to. Even if it's not practical, I find it to be very fun and often very educational. Something about building something from the ground up by yourself is just so much more appealing the slapping together premade blocks.

For example I still haven't found a workable way to handle the non-linear NES DAC behavior.

I'm currently using a monster sized lookup table (0x80*0x10*0x10 2-byte entries), and run DMC/Tri/Noise output through it... but that's only really working because I'm using the absolute value rather than the difference from the previous output. I can see how when working with differences it becomes more complicated.

As shown, a square wave of any frequency (width) can be approximated by one set of pre-computed transitions;

Just one set? I got the impression you would need multiple sets from the Implimentation section in your doc... you give 3 different examples of when the transition occurs. Or do you just keep one set with a really high resolution (say the NES's ~1789772/sec)?


Now this raises up some other questions I have for ya ;D

I see how this can be implimented for Squares. And even for the Noise channel (since it's similar). But what about the Tri and DMC? Do you put in the ripples for each step of the Tri? That seems like it would get really complex for higher frequency Tri notes (Kirby's Adventure has high Tri notes all over the place). And the DMC's output is constantly changing.... do you catch the transition of every step? They seem like they'd overlap.

I'll admit I'm not that great at documenting things clearly :)

Hahah. Just had a few questions. Your stuff is a lot easier to follow than some other docs I've read ;)

The added section to your doc and this post really cleared a lot of things up. I'm going to start on another core with this new info shortly.

Thanks again for all the info and clarifications and stuff. ^^




SubjectOne more Q new  
Posted byDisch
Posted on7/10/04 11:08 PM
From IP66.82.9.38  



I understand that the ripples don't change as the width of the wave changes... but what about the height? Would 2 squares playing the same note at 2 different volumes have the same shaped ripples? or would the quieter wave have smaller ripples?




SubjectRe: Win32 tracker new  
Posted bytepples
Posted on7/15/04 2:05 PM
From IP68.54.20.186  



If anybody wants to put in effort to port NT2, see
http://pinocchio.jk0.org/nt2/




SubjectRe: Win32 tracker new  
Posted bydXtr
Posted on7/15/04 8:08 PM
From IP194.47.158.137  



I was actually on my why to convert it when it was first released... but it halted after a week... it was so damn much to look through and no comments =/
So I spent around a week cleaning up and commenting the code.. but I was going so slow that I dropped it. Guess I didn't have the motivation (or something). I think it would be easier to just write a new one... but what do I know

sorry for misspellings


SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/19/04 5:35 PM
From IP199.170.89.144  



I have released an update to Blip_Buffer. It's more efficient and (hopefully) simpler to use. I also added two new sound emulators (GameBoy and SEGA Master System) and over a dozen samples of the quality Blip_Buffer allows. The following generates 100 frames of band-limited square wave into a buffer:

Blip_Buffer buf;
// ... configure buf size and time units per sample

Blip_Wave<3,100> wave;
wave.output( &buf );
wave.volume( 1.0 );

int amplitude = 25;

for ( int n = 100; n--; )
{
while ( wave.time() < frame_duration )
{
amplitude = -amplitude;
wave.amplitude( amplitude ); // change amplitude
wave.delay( clocks_per_sec / 2 / 1000 ); // delay (1kHz)
}
wave.end_frame( frame_duration );
buf.end_frame( frame_duration );

// samples are ready to be read out of buf
unsigned samples_read = buf.read_samples( sample_buffer, max_size );
// ...
}





SubjectRe: Emulation Sound Quality new  
Posted byRichter X
Posted on7/19/04 6:42 PM



I have a question. Could this technique be used on other things like YM#### synthesizers, the Namco106, or the VRC6?




SubjectRe: Emulation Sound Quality new  
Posted byJsr
Posted on7/19/04 8:34 PM
From IP62.127.14.59  



I have implemented Blip_Buffer in my NSF player.
It required some small changes to get working in VC++, but now it works and it sounds perfectly fine!

A really good work.




SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/20/04 07:40 AM
From IP199.170.89.103  



I have a question. Could this technique be used on other things like YM#### synthesizers, the Namco106, or the VRC6?

Yes; a square wave, the Namco 106's saw waves (which are made up of coarse steps rather than smooth ramps), the NES triangle wave, etc. work well. Blip_Buffer is for discontinuous waveforms, which have mostly flat regions divided by sharp transitions, so they need special attention to avoid exceeding the Nyquist limit. I've actually already written emulators for Namco 106 and VRC6 (but haven't added them to the library).

I haven't read about YM#### but it's my impression that they're FM sound chips; if they are then I think they wouldn't benefit from Blip_Buffer. I imagine an FM chip emulator is a very different beast (I've never really looked at how they work).


If anyone has a problem getting it to compile (even if a solution is found), let me know the problem (and solution) so I can correct the source code and spare others from the same issue.





SubjectFM new  
Posted bytepples
Posted on7/20/04 3:29 PM
From IP68.54.20.186  



Because the FM chips already seem to output relatively smooth waveforms, I think just 4x oversampling (that is, render at 192000 Hz, low-pass filter, and decimate to 48000 Hz) would work with the FM chips.




SubjectRe: Emulation Sound Quality new  
Posted byJsr
Posted on7/20/04 8:29 PM
From IP62.127.18.55  



Everything seems to be fixed in the new version.

But one problem in the first version when compiling with VC++ was "fatal error C1001: INTERNAL COMPILER ERROR" on line 263 in blip_buffer.h.
To fix that it was only to move that function out of the class declaration. I think that error is generated when the compiler have problems optimizing, or something.




SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/21/04 12:42 PM
From IP199.170.89.148  



Regarding emulating FM-type sound chips, I've looked into this more and it seems it would help after all. A Blip_Wave can easily be used as a downsampler:

int const phase_range = 1024;

// some complex continuous function, like FM generator
int wave_function( int phase );

Blip_Buffer buf;
buf.units_per_sample( 8 ); // run waveform at 8x sampling rate
// ...

Blip_Wave<3,100> wave;
wave.output( &buf );
wave.volume( 1.0 );

int phase = 0;

for ( int n = 100; n--; )
{
while ( wave.time() < frame_duration )
{
wave.amplitude( wave_function( phase ) );
phase = (phase + 1) % phase_range;
wave.delay( 1 ); // we're running at the oversampling rate
}
wave.end_frame( frame_duration );
buf.end_frame( frame_duration );

// samples are ready to be read out of buf
unsigned samples_read = buf.read_samples( sample_buffer, max_size );
// ...
}

This performed fairly efficiently, but it's such a specialized and possibly useful application that I just wrote a specialized Blip_Resampler which is about 4 times faster than the above. The resampler is nice because it makes it's easy to convert an already-written emulator to output to it instead of a sample buffer: just tell the emulator you're working at a higher sampling rate, and change its sample generation loop to write to the resampler rather than directly to the sample buffer (if there's no sample loop, i.e. you call a function to get the next sample, then the above will perform just as well).

I'm seeing if I can find enough documentation about an FM chip to do a full emulation of one and see how it performs. These things are strange and interesting beasts to me at the moment :)

It will be nice if Blip_Buffer can accommodate continuous and discontinuous waves equally well and efficiently.





SubjectRe: FM new  
Posted byblargg
Posted on7/24/04 02:18 AM
From IP199.170.89.70  



As a follow-up to the question of using Blip_Buffer for resampling FM oscillators, it's working well.

To test the Blip_Resampler I'm working on, I made an FM oscillator that runs at 4x oversampling. I hacked the FM oscillator into my NSF player in the square channels to see how it sounds. I gave it modulation parameters to produce some fairly high harmonics in order to find out how bad it aliases. I used Castlevania 3 track 2 as a test. The CPU usage is really low, something like 4% for a 4x resampler. You really only need one total; if you had more than one FM oscillator you'd calculate them in parallel.

http://www.io.com/~greens/temp/Castlevania_3_fm.mp3

This really got me thinking about converting APU register writes into generalized note commands and being able to plug in any kind of instrument. I don't think anything will ever sound as good as the original waveforms, but it'd be a fun exercise.

There is some quality trouble with Solstice and Blip_Buffer 0.2. I tracked the problem down to some changes in implementation. A Blip_Synth<2,15> for the noise channel was the best solution I found. The first parameter is really the width of the impulse used internally, and a wider impulse doesn't always mean higher quality. I plan on investigating the matter further, since it touches on some annoying aspects of implementation.





SubjectRe: FM new  
Posted byFx3
Posted on7/24/04 02:31 AM
From IP201.1.130.254  



If you could reach the CPS1 sound output (including the drums by using the noise channel I suppose)... just "dreaming" I guess :)




SubjectRe: FM new  
Posted byRichter X
Posted on7/24/04 02:53 AM



Ohhh, man, that is beautiful. I hope Disch gets an earful of that. :)




SubjectRe: FM new  
Posted byDisch
Posted on7/24/04 03:07 AM
From IP66.82.9.15  



Haha... well I'm rather curious as to how he's doing FM synthesis.

Do you have any good docs to link me to on FM Synth, blargg? ^^. I'd love to replace my existing VRC7 code with my own routines... I'm less than thrilled with having borrowed code.




SubjectRe: FM new  
Posted byblargg
Posted on7/24/04 09:36 AM
From IP199.170.89.103  



I looked at some of the FM chip emulators and am fairly sure I'm not going to attempt to write one; they seem quite complex and finding bugs would be difficult I think. I don't really like the sound of them anyway (I do like many SEGA Genesis tunes). All I implemented was the basic formula I saw of sin( angle + modulation_index * sin( modulation_angle ) ). It's fun to play with if you set up a few sliders and a waveform display in a little real-time synthesizer. I wrote it just to develop Blip_Resampler, so someone else can write a real FM synth with band-limiting (and for all I know, current FM synth emulators don't have problems with aliasing in the first place).

Here is an fm synth I have experimented with, using the Blip_Resampler that's in development. I wrote it using floating-point for clarity; fixed-point with a sine table is about 10x faster. I don't show the code which assigns the resampler's output to a Blip_Buffer.

#include "Blip_Resampler.h" // not in Blip_Buffer library yet

int const oversample = 4; // 4x oversampling works well
Blip_Resampler<oversample> resampler;
double phase;
double mod_phase;

double const sample_rate = 44100;

void fm_wave( double freq, blip_time_t duration )
{
double period = sample_rate * oversample / freq;

// I used these parameters for the "instrument" in the sample
double step = pi * 2 / period;
double mod_factor = 2.5 * pi;
double mod_step = pi * 2 / (oversample * sample_rate) * 5.005 * freq;

// Find number of 4x oversamples within duration in system clock cycles
size_t count = resampler.count_samples( duration );

// Iterator necessary to help optimizer inline everything
Blip_Resampler<oversample>::Iter iter;
iter.begin( resampler, count );

while ( count-- )
{
// FM function
double f = sin( phase + mod_factor * sin( mod_phase ) );

// Add it as -128 to 128 sample
iter.add_sample( 128 * f );

// Increment phases
phase += step;
if ( phase >= pi * 2 )
phase -= pi * 2;

mod_phase += mod_step;
if ( mod_phase >= pi * 2 )
mod_phase -= pi * 2;
}

// End resampling and frame
iter.end();
resampler.end_frame( duration );
}





SubjectRe: Emulation Sound Quality new  
Posted by<_Hyde_>
Posted on7/27/04 5:13 PM
From IP207.62.63.210  



Here is my feedback on your Nes_Apu and Blip_Buffer libraries:

- I had no problems at all compiling the latest version on MSVS.NET. Everything went smoothly...

- Trying to figure out what function calls ought to be called wasn't that hard either. The demos you've included (APU and player) showed me what I needed to know.

- Asserts certainly helped.

- Trying to figure out how to use the data generated by the output function (blip buffer) was a pain in the ass, mostly because I'm not really experienced with sound programming. At first, I managed to get the sound samples out, but it all sounded messed up. After spending some time looking at the source I realized that the sample data output by your library is in a 16-bit *signed* format, which was not welcome at all by Allegro. So, I decided to use another sound library to output the data, namely PortAudio, which seems to work quite well.

Now here are some questions:

- Is there any way you could output samples in an unsigned manner?

- How can I find out the amount of cycles "stolen" (killed, murdered, whatever) by the DMC unit as it fetches sample data? Also, is there any way of knowing the exact time (timestamp) at which those cycles were stolen? Or, do you think all of this is not needed at all?

hydesprojects.cjb.net


SubjectSigned audio new  
Posted bytepples
Posted on7/28/04 00:07 AM
From IP68.54.20.186  



"After spending some time looking at the source I realized that the sample data output by your library is in a 16-bit *signed* format, which was not welcome at all by Allegro."
To convert 16-bit signed audio to unsigned or vice versa, just XOR each sample value with 0x8000.




SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on7/28/04 03:29 AM
From IP199.170.89.78  



[...] After spending some time looking at the source I realized that the sample data output by your library is in a 16-bit *signed* format, which was not welcome at all by Allegro. So, I decided to use another sound library to output the data, namely PortAudio, which seems to work quite well.

Just about everything I've encountered uses signed samples when they are 16 bits (8 bit samples are common in both formats). If you use unsigned you've got to add a compensation offset when adding or multiplying samples. This function swaps between signed and unsigned representation:

    void toggle_signedness( int16_t* p, size_t s ) {
while ( s-- ) {
*p ^= 0x8000;
++p;
//*p++ ^= 0x8000; // might trigger obscure compiler bugs :)
}
}

Is there any way you could output samples in an unsigned manner?

Convert the buffer in-place; the only downside is the tiny performance hit. Blip_Reader allows inline reading from a Blip_Buffer, but it's much less friendly and not well documented yet. Blip_Reader will be better documented in a future release.

How can I find out the amount of cycles "stolen" (killed, murdered, whatever) by the DMC unit as it fetches sample data? Also, is there any way of knowing the exact time (timestamp) at which those cycles were stolen? Or, do you think all of this is not needed at all?

I measured 4 CPU cycles stolen by a DMC memory read (see the APU reference), which you can account for when your DMC reader callback is invoked. Regarding adjustment of the CPU, I'm going to start a new thread for the issue since it's involved.





SubjectRe: Emulation Sound Quality new  
Posted by<_Hyde_>
Posted on7/28/04 7:45 PM
From IP207.62.63.210  



Managed to get everything sounding OK through Allegro (thanks for the tip on signed/unsigned data). Now, I've come up with yet another question that is not really related to your library. Could you give an example of how to use the value returned by the earliest_irq function?

Regarding adjustment of the CPU, I'm going to start a new thread for the issue since it's involved.

I'm looking forward to that.



hydesprojects.cjb.net


SubjectRe: Signed audio  
Posted by<_Hyde_>
Posted on7/28/04 7:47 PM
From IP207.62.63.210  



Thanks.

hydesprojects.cjb.net


SubjectRe: Emulation Sound Quality new  
Posted byblargg
Posted on8/14/04 04:18 AM
From IP199.170.90.27  



I've released a new version of Blip_Buffer (0.3.0). I added a beta/ directory
for new things that haven't been polished yet. Included is the previously
mentioned resampler for mixing oversampled buffers into a Blip_Buffer, and a
miniature Blip_Buffer implementation in C (which also might help in
understanding how it works).

http://www.slack.net/~ant/nes-emu/libs.html#Blip_Buffer

I cleaned up the interface a bit. Now things are clearer than the old
units_per_sample() interface:

long samples_per_sec = 44100; // 44.1 kHz
long clocks_per_sec = 1789773; // 1.79 MHz

// Set up a buffer
Blip_Buffer buf;
if ( !buf.sample_rate( samples_per_sec ) )
error( "out of memory" );
buf.clock_rate( clocks_per_sec );

This creates a buffer of maximum length (which is around 65000 samples and uses 128K of memory). The length can be specified (in milliseconds) in
order to conserve memory:

buf.sample_rate( samples_per_sec, 1000 / 2 ); // 1/2 second length

I broke the demos into several files and functions, since the old huge function
was a bit hard to comprehend. I added more demos of how to buffer sound and
read it out, since this seemed to be an unclear area. I also wrote a better
demo of how to use Blip_Wave to make a simple square wave class.

I added and clarified the notes, and gave Blip_Synth its own header file to
make it easier to refer to.

The low-pass and high-pass equalization parameters are now in natural units.
The low-pass cutoff is specified in Hz and the attenuation at 22kHz in dB (-6.0
dB = 50%). The high-pass filter's breakpoint (-3dB point) is also specified in
Hz. This makes it simpler to change the output sample rate without disturbing
the equalization parameters. For NES sound I use a high-pass breakpoint at 33
Hz, a low-pass rolloff point at 8800 Hz and -8.6 dB attenuation at 22kHz.

I haven't found as much help as I'd like in testing it, so please report any
compilation problems. I kept the previous version of the library on the web
page just in case there are any major compilation problems :)

Thanks to everyone who has given feedback.





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

Memblers' homepage             Contact Me

Forums powered by WWWThreads Demo