Described here is a class used in the generation of audio frequency sinusoidal signals and white noise using a PC. The generator hardware must include a DAC of no more than 16-bit resolution and must use the double-buffered memory technique. This means that while one DMA channel transfers the data from one buffer (buffer1) to the converter, the CPU refreshes the other buffer (buffer2) with new data. Also, each time that the DMA finishes an operation on a buffer, an interrupt to the CPU must be generated. The buffers must be allocated in contiguous memory locations.
To produce sinusoidal waves, a fractional-N synthesizer is emulated by the class (see the figure). The adder inputs are fed by a constant Index number and by the output address accumulator. The adder generates a new address equal to the sum of the previous address and the Index number, synchronized with the sampling frequency clock (SamFrq). The most weighted outputs of the address accumulator are connected to the ROM address lines, which contains the samples of a sinusoidal waveform period. The ROM data lines are connected to the DAC, reproducing an analog signal corresponding to the ROM samples. The adder rate is:
fadder = SamFrq*lndex/adder_size
If SamFrq/adder_ size = 1 (condition1), the output frequency is equal to the Index. When adder_size = ROMsize* factor, then:
factor = SamFrq/ROMsize
Given the sampling frequency and the ROMsize, factor is the value that makes (condition1) true. The output signal frequency is equal to the Index number. The frequency resolution of the generator is fixed by the variable type of the Index.
The function int random (int value-1) from Borland is used to generate white noise. It returns a random integer, between 0 and −1.
The C++ class EdGen is declared in the EdGen.h file (Listing 1). The class could be initialized in two modes—noise or tone—according to the constructor used. In the noise mode, the default constructor must be used. The tone constructor takes three unsigned integers as arguments: sampling frequency, tone frequency, and tone initial phase. The last one is a default argument and may be used to initialize the starting phase of the tone.
An object initialized in one mode can be changed “at flight” to the other one, overwriting the public data member SignalType. However, if the object was initialized in the noise mode, the member function InitTone must be called before changing to the tone mode. The member function gelvalue returns a new value for the tone or noise each time it’s called. The members functions setToneFrq and get-ToneFrq may be used to set or get the tone frequency without stopping the generation. These functions are useful to produce frequency sweeps.
As mentioned previously, the hardware must generate an interrupt to the CPU at the end of each DMA transfer. A sample interrupt service routine is shown (Listing 2).
If the hardware has several channels, independent objects EdGen can be created for each channel.