Nes_Snd_Emu 0.1.7 Notes ----------------------- Overview -------- The library includes a NES APU sound chip emulator, sound sample buffer, support for state snapshots, a Namco 106 sound chip emulator, a Konami VRC6 sound chip emulator, and a nonlinear sound buffer. The sound chip emulators handle reads and writes to their registers and generate samples into one or more sound buffers. Register accesses take a CPU clock count, relative to the current time frame. When a time frame is ended all samples from it are added to the sound buffer. The sound buffer accumulates samples generated by the sound chips and allows them to be read out at any time. The sample rate can be adjusted freely. Using the APU ------------- Simple_Apu is recommended instead of Nes_Apu when using the library for the first time (see Simple_Apu.h for reference). Its source code demonstrates basic use of the APU. To use Nes_Apu (or the other sound chips), its output must be routed to a Blip_Buffer. Then pass CPU reads and writes to the sound chip, end its time frame periodically and read samples from the sound buffer. Nes_Apu apu; Blip_Buffer buf; Setup buf.sample_rate() Set sample rate and allocate memory for buffer buf.clock_rate() Set clock rate (1789773 for NTSC NES) apu.output() Route APU output to buffer apu.dmc_reader() Set function APU calls to read memory Emulation apu.write_register() Emulate write to APU register apu.read_status() Emulate reads APU status register apu.end_frame() Generate samples for time frame buf.end_frame() Make samples for time frame available for reading buf.samples_avail() Number of samples in sound buffer buf.read_samples() Read samples out of sound buffer Nonlinear Sound Emulation ------------------------- Nonlinear_Buffer is a special sound buffer which emulates the non-linearity of the NES APU sound chip on the triangle, noise, and DMC channels. It can be used in place of Blip_Buffer, except that the APU should be assigned using buf.enable_nonlinearity( apu ), and other sound chips using other_sound_chip.output( buf.buffer() ). Blip_Buffer ----------- Basic Blip_Buffer operation is covered. Further features like frequency equalization and other features are not described. For more information and examples of using Blip_Buffer, download the full Blip_Buffer library package Emulation Accuracy ------------------ Nes_Apu accuracy has some room for improvement, especially regarding IRQ handling. I am still working on reverse-engineering the NES APU and designing an improved APU. Nes_Namco and Nes_Vrc6 accuracy is based on the documentation I have. I have made many tweaks to make them sound similar to a couple of samples I've heard of the real thing. Solving Problems ---------------- If you're having problems, check the following: - If multiple threads are being used, ensure that only one at a time is accessing objects from the library. This library is not thread-safe. - Turn the compiler's optimizer is off. Sometimes an optimizer generates bad code. - Enable debugging support. This enables assertions and other run-time checks. - See if the demo works. If not, contact me. Error handling -------------- Functions which can fail have a return type of blargg_err_t, which is a pointer to an error string (const char*). If the function is successful it returns blargg_success (NULL), otherwise it returns a pointer to an error string. To allow compatibility with older C++ compilers, no exceptions are thrown by any of the modules. The library is exception-safe, and any exceptions which occur are not intercepted. Any exceptions thrown by the standard library or caller-supplied functions are not caught. The library uses BLARGG_NEW instead of new for allocations. By default, BLARGG_NEW is #defined to new (nothrow) so that a failed allocation won't cause an exception. This can be overriden in your config.h file (see below). Significant violations of the documented interface are flagged with debug-only assertions. Failure of these usually indicates a caller error rather than a defect in the library. Configuration ------------- The header "blargg_common.h" is used to establish a common environment, and is #included at the beginning of all library headers and sources. It attempts to automatically determine the features of the environment, but might need help. If HAVE_CONFIG_H is defined in the compiler options, the file "config.h" is included at the beginning of each library header file, allowing configuration options for the library to be set. It's fine if other libraries also use this scheme, as they won't conflict. I have attempted to design the library so that configuration can be done without modifying any of the library sources and header files. This makes it easy to upgrade to a new version without losing any customizations to its configuration. Some parts of the library might depend on the order of bytes in multibyte types. If so, they will cause a compilation error if the order can't be determined (rather than silently fail). If this occurs, define the appropriate symbol. For big-endian (most significant byte first, i.e. Motorola 68000, PowerPC), #define BLARGG_BIG_ENDIAN to 1. For little-endian (least significant byte first, i.e. Intel x86), #define BLARGG_LITTLE_ENDIAN to 1. Older C++ compilers might not support bool. Support is provided where bool is not available, but the compiler's support of bool might not be properly determined. If errors occur in "blargg_common.h" in the bool section, #define BLARGG_COMPILER_HAS_BOOL to 1 if your compiler supports bool, otherwise 0. If your compiler doesn't support static_cast<>, #define STATIC_CAST( type ) to (type) so that old-style casts are used instead. If your compiler supports namespaces, blargg_common.h uses standard headers with the "c" prefix to avoid bringing names from std into the global namespace. If your compiler supports namespaces but this isn't being detected by blargg_common.h, #define BLARGG_COMPILER_HAS_NAMESPACE to 1. Every library source file has #include BLARGG_SOURCE_BEGIN after all other #include lines, to allow setting compiler options and disabling warnings for library sources only. By default, this is #defined to "blargg_source.h". In library source files, #include BLARGG_ENABLE_OPTIMIZER is used before performance-critical code. By default it doesn't do anything, since enabling compiler options involves compiler-specific #pragma directives. After you've got the library working, you can enable platform-specific optimizations by #defining BLARGG_NONPORTABLE to 1. Contact me if you encounter any problems that only occur when these are enabled. If you have any problems with "blargg_common.h", contact me. Boost Compatibility ------------------- Boost is a collection of small, useful C++ libraries which provide basic services. If it's not installed in your environment or your environment isn't supported, a tiny substitute is included in the "boost/" directory. This implements only that boost functionality used, and is written to work with most compilers. If boost is already installed, you can delete the included "boost/" directory. For more information about boost, see http://boost.org/