Sunteți pe pagina 1din 0

An Audio Amplifier System with

Digital Delay-Based Effects







Submitted To

Yaoqing Yang
Brian Evans




Prepared By

Jason Keller
Joel Koepke



EE464 Senior Design Project
Electrical and Computer Engineering Department
University of Texas at Austin

Fall 2004
ii
CONTENTS

LIST OF FIGURES............................................................................................................ iv
LIST OF TABLES................................................................................................................v
EXECUTIVE SUMMARY ................................................................................................ vi

1.0 INTRODUCTION........................................................................................................1
1.1 PROJECT BACKGROUND..............................................................................1
1.2 REPORT ORGANIZATION.............................................................................1
2.0 DESIGN PROBLEM STATEMENT.........................................................................1
3.0 DESIGN PROBLEM SOLUTION.............................................................................3
3.1 PREAMPLIFIER................................................................................................3
3.2 DIGITAL EFFECTS ..........................................................................................4
3.2.1 Data Transfer and Timing .............................................................5
3.2.2 Effects Algorithms ..........................................................................6
3.2.3 Switching Between Effects .............................................................7
3.2.4 Economic Analysis ..........................................................................7
3.3 POWER AMPLIFIER........................................................................................7
3.4 POWER SUPPLY...............................................................................................8
3.5 AMPLIFIER SYSTEM ENCLOSURE............................................................9
4.0 DESIGN IMPLEMENTATION...............................................................................10
4.1 PREAMPLIFIER..............................................................................................10
4.2 DIGITAL EFFECTS ........................................................................................10
4.3 POWER AMPLIFIER......................................................................................11
4.4 POWER SUPPLY.............................................................................................12
4.5 AMPLIFIER SYSTEM ENCLOSURE..........................................................12
5.0 TEST AND EVALUATION......................................................................................12
5.1 FREQUENCY RESPONSE.............................................................................13
5.2 TOTAL HARMONIC DISTORTION............................................................14
5.3 DIGITAL FILTER IMPULSE RESPONSES................................................14
6.0 TIME AND COST CONSIDERATIONS................................................................19
iii
7.0 SAFETY ASPECTS OF DESIGN............................................................................20
8.0 CONCLUSIONS AND RECOMMENDATIONS...................................................21
REFERENCES....................................................................................................................23
APPENDIX A SCHEMATICS.................................................................................... A-1
APPENDIX B DIGITAL EFFECTS CODE ...............................................................B-1
APPENDIX C PROJECT PICTURES....................................................................... C-1
APPENDIX D IMPULSE RESPONSE UTILITY CODE........................................ D-1








iv
LIST OF FIGURES

1 Top-Level Block Diagram for the Amplifier System.......................................................3
2 Delay-Based Effects Block Diagram................................................................................5
3 Frequency Response of the Amplifier System................................................................13
4 Medium-Power THD Measurement ...............................................................................15
5 FIR Echo Time Domain Impulse Response....................................................................16
6 FIR Echo Frequency Domain Impulse Response ...........................................................16
7 Flange Time Domain Impulse Response ........................................................................17
8 Flange Frequency Domain Impulse Response................................................................18
9 Reverb Frequency Domain Impulse Response...............................................................19
10 DSP CPU Load Graph For Different Effects..................................................................22



v
LIST OF TABLES

1 Delay Times for Different Effects ....................................................................................6
2 Itemized Budget for the Entire Amplifier System..........................................................20
3 Initially Proposed Budget for the Entire Project.............................................................20

vi
EXECUTIVE SUMMARY

The following report thoroughly details the process and the ultimate results of the design and
construction of an audio amplifier system with delay-based digital effects, as conducted by Jason
Keller and Joel Koepke. The report begins with a discussion of the motivations for undertaking
the project and a detailed explanation of the reports organization. A project definition then
follows with a complete explanation of the design problem as well as the initial design
parameters. These specifications include incorporating the option of bypassing or selecting from
several digital effects, setting the maximum total harmonic distortion allowed, and describing the
functional elements of each separate component of the project. We then discuss the modular
approach we took to the project and the benefits it yielded.

Next, we present the solutions to meet our project specifications as well as the alternatives we
considered for each major project component, including the preamplifier, the digital effects, the
power amplifier, the power supply, and the system enclosure. Following this, we illustrate the
unforeseen challenges we faced in the implementation of our solutions and the changes that they
forced us to make to our original plans.

The methods for evaluating the project are then defined and the results produced by these
methods are shown. Then, we compare this data to our original expectations in order to
determine the success of the project. A discussion of the time and cost considerations of the
project follows, along with the safety issues that relate to a high voltage audio amplifier system.
Finally, we summarize the contents of the report and give a full list of the references used
throughout it. In addition, schematic diagrams, code produced, and project photos are given in
Appendices A through D.





1.0 INTRODUCTION

This final report serves as a comprehensive record of the work we completed and the results we
obtained while carrying out our senior design project plan. It focuses on all aspects of the design
process and details the implementation and testing of our final product: an audio amplifier
system with digital effects. We began the project with high expectations, and this report will
illustrate our performance in meeting our goals.

1.1 PROJECT BACKGROUND
The project team consists of Jason Keller and Joel Koepke, who are both electrical engineering
undergraduate seniors at The University of Texas at Austin. The project was initially proposed
as a result of Jason and Joels interest in audio electronics and digital signal processing applied to
music. The faculty sponsor for the project is Dr. Brian Evans, whose research and teaching
efforts focus on embedded real-time signal and image processing systems. While the project has
not advanced Dr. Evanss research nor the audio electronics industry, it has certainly
strengthened Jason and Joels knowledge and interests.

1.2 REPORT ORGANIZATION
To begin the report, we will give a complete definition of the design problem in terms of what
we set out to accomplish. Then we will describe the operating principles of our design solutions
as well as the decisions we made and the alternatives we considered leading up to them.
Following this, we will discuss the challenges we faced during the implementation of our design
and the deviations we made from our original plans. Additionally, we will detail the methods we
used to evaluate our final product, and we will provide data to compare with our initial
specifications. The report will conclude with a discussion of the time and cost considerations of
the project and the safety and ethical issues relating to it.

2.0 DESIGN PROBLEM STATEMENT

In the proposal submitted on September 14, 2004, we defined our project to design and construct
a single-channel (monaural) audio amplifier system with digital effects. There are four main
2
components of the system: the preamplifier, the digital effects, the power amplifier, and the
power supply. Following along the complete amplifier system path, the preamplifier first passes
the input signal through a three-band analog equalizer whereby the user can manipulate the
signals frequency content. This analog signal is then converted to a digital signal and processed
for the desired effect using a Digital Signal Processor (DSP). The enhanced output from the
DSP is then converted back to an analog signal and fed into a power amplifier that provides the
appropriate power to a speaker. The power supply creates the necessary DC voltage rails for the
preamplifier and power amplifier circuits. At the projects inception, we also included the
following design parameters:

Incorporate the option of bypassing or selecting from multiple delay-based digital effects
including echo, reverb, chorus, and flange

Reproduce the line-level audio input signal with a Total Harmonic Distortion (THD) of less
than one percent (while bypassing the digital effects)

Provide 60 Watts of output power to an eight-ohm speaker load, and include the option of
directly outputting the preamplified signal to a higher impedance load such as headphones

Enclose the final product in a rugged casing with front-end user controls for ease of use and
isolation from any safety hazards

Power the amplifier system from a single 120 Volt wall outlet

The aforementioned separate components of the project allowed us to approach the overall
design problem in a modular fashion. Their inherent modularity permitted us to work on the
different parts of the project concurrently. As a result, we tested and debugged each component
of the amplifier separately and problems in one component did not hinder progress on other
project components. Also, we connected the components together as soon as possible so that we
could properly address any problems in their interaction. The block diagram for the project,
shown in Figure 1 on the following page, further illustrates this modularity.

Creating the necessary analog-to-digital (A/D) and digital-to-analog (D/A) conversions that
interface the DSP to the rest of the amplifier system is a substantial task that we did not plan to
undertake. Therefore, we made the crucial early decision to use a Texas Instruments (TI) DSP
Starter Kit (DSK) in order to perform this task. Consequently, this decision narrowed down our
selection of a DSP to a few choices, from which we selected the floating point TMS320C6713
3


Figure 1. Top-Level Block Diagram for the Amplifier System

processor because of our familiarity with this DSP family and its high performance capabilities.
The DSK was the most substantial and expensive component of the project, and thus we
designed all other components around its limits. For example, the input and output capabilities
of the DSK governed the maximum output and input voltages of the preamplifier and power
amplifier, respectively.

3.0 DESIGN PROBLEM SOLUTION

After we defined our project thoroughly and decided on the approach we would take, we faced
the immense challenge of producing solutions to meet all of our goals. We will now discuss the
decisions that we made and the alternatives that we considered for each of the modular
components of the project mentioned above. We will also talk about the theory and operating
principles for each module as well as the economic factors that affected them.

3.1 PREAMPLIFIER
The main purpose of the preamplifier is to allow the user tonal control of the final output using
an equalizer, which is an amplifier that boosts or attenuates specified frequencies of the input
signal. We first attempted to design the equalizer using techniques that we learned in our
4
Electronic Circuits II course by creating three active filters with gain control, corresponding to
the low, middle, and high frequencies of the equalizer. We placed these filters in parallel and
added the output of each filter together using a summing op-amp circuit. However, the
simulated frequency response of this circuit had significant distortion, since we neglected to take
into account the different phase responses of each filter. After further research, we concluded
that a series filter circuit with feedback was necessary to avoid such phase problems.

We modeled two such series circuits from Walter Jungs Audio IC Op-Amp Applications [1, pp.
131-141] and Craig Andertons Electronic Projects for Musicians [2, pp. 138-141]. We chose to
use the design from Andertons book for our project because it produced the flattest frequency
response with its controls in neutral positions, and it was highly cost effective as its most
expensive components were the potentiometers needed for frequency control. This design is a
parametric equalizer, which allows the user to boost or cut specified frequencies just as a normal
equalizer does, but also has the ability to adjust the location and shape of the center frequency
filter. This allows the user greater flexibility for altering specified frequencies, and thus exceeds
the specifications put forth in our original proposal. The schematic for this parametric equalizer
circuit (as modeled in PSpice) is given in Appendix A.

3.2 DIGITAL EFFECTS
We implemented the digital effects with delay-based filters that form their output from a mix of
their current input along with past inputs and possibly past outputs, or feedback. The only effect
we implemented that does not require feedback is the simple echo, and it therefore has a finite
impulse response (FIR). All of the other effects that we implemented require feedback in their
algorithms, and consequently have infinite impulse responses (IIR). We wrote the digital filters
in the C programming language since TIs Code Composer Studio (CCS) software environment
has an excellent C compiler. A block diagram depiction of delay-based effects, derived from
Curtis Roadss The Computer Music Tutorial [3, pp. 436-440], is shown in Figure 2 on the
following page.

The features of the DSK strongly influenced our design solution for the digital effects. For
instance, each effect has a different algorithm, but in all cases we used a circular delay buffer
5


Figure 2. Delay-Based Effects Block Diagram

to store past inputs and outputs as floating point numbers in the DSKs 16 Mbyte external RAM
chip. Also, the quality of the effects and the digital audio in general is governed by the
capabilities of the DSKs codec, which has 16 bits of resolution and 11 different software-
selectable sampling rates. We chose a 44.1 kHz sampling rate to ensure CD-quality frequency
content in our effects.

3.2.1 Data Transfer and Timing
The main challenge to writing our effects algorithms was setting up the necessary data transfers
and timing to keep audio streaming in and out of the DSP in real-time. We first tried polling the
DSPs serial port in an infinite loop to accomplish this, but this method proved to be too
computationally expensive to continue our efforts with it. Then we attempted to use software
interrupts triggered by the serial port, which was more efficient than polling but did not allow for
the efficient transfer of data to and from the external RAM. Finally, we settled on a solution that
uses the DSPs Enhanced Direct Memory Access (EDMA) controller to transfer data to and from
anywhere on the DSKs memory map, independent of the DSPs processing resources.
Combined with hardware interrupts that signal the DSP when an EDMA transfer is complete, the
EDMA provided a solution that could easily stream audio at 44.1 kHz and leave plenty of time
for further data processing. A complete version of our C code illustrating how the EDMA
transfers and digital effects algorithms work in given in Appendix B.

6
3.2.2 Effects Algorithms
We implemented the following delay-based effects for our project, in order of increasing
computational complexity: echo (FIR), echo with feedback (IIR), flange, chorus, and reverb.
The different effects are defined by their different delay times [4, pp. 40-41], as shown in the
table below.

Table 1. Delay Times for Different Effects
Effect Delay Time (ms) Notes
Flange 0 - 15 Produces "whooshing" sound
Chorus 10 - 25 Resembles two instruments playing at once
Reverb - Many delays give a spatial effect
Echo > 50 Two separate sounds can be heard

The FIR echo algorithm calculates the current output buffer value by adding the current input
buffer value to an input buffer value that occurred a certain amount of time in the past, specified
by a number of samples. The IIR echo adds the current input to a past output buffer value, thus
creating multiple echoes. Each algorithm uses decay factors to specify the audible level of the
echo relative to its original sound.

The flange and chorus algorithms are variable delay effects that both use the same basic
structure. They use a lookup table generated at the programs initialization to vary the number of
delayed samples over time. The lookup table is called the low frequency oscillator (LFO) and
can be any shape, although these effects usually use a sine wave or triangle wave LFO.
Additionally, flanging uses feedback and chorusing does not [4, pp. 42-43].

Reverb is the most complex effect that we created. We modeled the effect after a well-known
algorithm known as Schroeder Reverb, which uses five to six different initial delay times
corresponding to the initial reflections of sound in a room. These initial echoes are then fed back
into the output buffer and mixed with the input buffer at two longer delay times analogous to
later reflections. The different echo delay times and decay factors are chosen to simulate the size
and shape of the virtual room that the input sound is coming from [5, pp. 289-304].


7
3.3.3 Switching Between Effects
To complete one of our initial objectives, we also needed a way to switch between different
effects. We did this by using built-in functions that work with the DIP switch on the DSK to
allow easy user input. A hardware interrupt function in the program is called whenever an
EDMA transfer is complete, which in turn calls the data processing function. We used if-
statements in the interrupt function to check the state of the DIP switch, and then call the effects
algorithm corresponding to that state.

3.3.4 Economic Analysis
The DSK, and hence the digital effects, had the greatest economic impact on the project.
However, we deemed it a necessary cost since it was specifically co-developed by TI and
Spectrum Digital for prototype development applications such as our project. We could have cut
our amplifier system cost significantly by designing and building our own interface to the DSP,
but we did not have the necessary time or resources to do so, and we do not plan to mass-produce
and sell our amplifier.

3.3 POWER AMPLIFIER
The main purpose of the power amplifier is to take a line-level input and amplify the signal so it
can drive a speaker load. There are numerous types of power amplifiers, but the most common
is the three-stage topology developed by H. C. Lin of RCA [6, p. 58]. The three stages of the Lin
design each play an important role in the amplification process. The first stage is a
transconductance amplifier, which buffers the input signal and amplifies it into a proportional
current. Next, the transimpedance amplifier receives the current from the first stage and converts
it to a high-level voltage. Finally, this high-level voltage enters the current amplifier stage which
increases the current so it can drive a speaker load.

In order to determine the amplifier design, we first had to decide which class of amplifier would
meet the THD requirement. The output stage, which determines the amplifier class, can be
implemented using one of the numerous output types including: A, AB, B, C, and D. However,
the only classes that suited our amplifiers output power and low-distortion requirements were
classes A and B. Theoretically, class A output stages produce the least amount of total
8
distortion, although they are very inefficient. Moreover, methods used to increase the class A
efficiency often lead to a substantial amount of transient distortion. Class B output stages
produce a nominal amount of crossover distortion, which can be reduced below the audible level
with careful design [6, pp. 142-150].

For our final design, we decided to accept the minor distortion caused by a class B power
amplifier in favor of its efficiency and simplicity, and selected an amplifier from Randy Slones
High-Power Audio Amplifier Construction Manual [6]. This amplifier design met all the
necessary specifications since it can produce an output of up to 100 Watts with a THD of less
than one percent. The entire cost for this design was minimal in comparison to other amplifier
designs with equivalent output power and was largely influenced by the price of the
complementary pair of output power MOSFETs. The schematic for our power amplifier is given
in Appendix A.

3.4 POWER SUPPLY
The power supply provides power to all the analog portions of our amplifier system. Since these
components require DC voltages to operate, it was necessary to convert the 120 Volts
AC
coming
from the wall outlet to the proper DC levels. The most common and well-known technique to do
this conversion is with a diode bridge rectifier (DBR). A DBR circuit works by passing an AC
voltage through a diode bridge, a grouping of four diodes, which outputs a full-wave rectified
voltage. A reservoir capacitor then smoothes this pulsating voltage, producing a near ripple free
DC voltage.

Before we could design our DBR circuit, we had to determine what DC voltages would be
necessary to produce a 60-Watt output from the power amplifier. We first calculated what the
required output voltage of the amplifier would be to produce the needed output power. Then,
accounting for the voltage drop across the diodes and the inherent voltage sag of the fully loaded
power supply, we found that a DC voltage of 45 Volts would suffice. In order to achieve this
DC voltage, the transformer must have an output of 26 Volts
RMS
, however since the amplifier
must have both a positive and negative swing, our design requires two 26-Volt
RMS
secondaries.
We then calculated the minimum power rating of the transformer. First, we doubled the
9
maximum output power of the amplifier due to the 50% efficiency of the design. Then, we
doubled the power again so we would be able to drive a smaller impedance load such as a four-
ohm speaker. Using nearly the same procedure, we calculated the necessary transformer output
voltages required to power all op-amps within the amplifier system.

To drive the power amplifier, our final design used a transformer rated at 420 Volt-Amperes with
two 28-Volt
RMS
secondaries. In addition, a 35-Volt-Ampere transformer with two seven-Volt
RMS

secondaries was used to power the op-amp circuitry. These transformers were the most
expensive analog components of our project, and therefore we added a cushion to their power
ratings to ensure that they would never enter potentially harmful operating regions. Also, the
benefits of a quality power supply justify its cost since the power it provides affects all other
components of the system.

3.5 AMPLIFIER SYSTEM ENCLOSURE
The final aspect of our design solution included constructing a rugged enclosure to house the
different components of the amplifier system and shield the user from any safety hazards. The
added reliability and security of the amplifier system provided by the enclosure did more than
justify its moderately low cost. The design of this enclosure was relatively straightforward and
consisted of measuring the correct dimensions to fit all of our components and providing a
simple means of input and output. We decided to use a wood base and plexiglass top so that the
user could see the product at work. A standard quarter-inch input jack mounted into the wooden
side panel allows for universal input, and an old speaker jack mounted into the opposite side
panel allowed for the painless connection of a speaker at the output. We purchased the parts for
the enclosure at a hardware store and built it with power tools that we own. Also, we
incorporated safety LEDs and large potentiometer knobs into the design to make it aesthetically
pleasing and easy to use. A photographic record of the enclosure as well as the different
components of the amplifier system is given in Appendix C.




10
4.0 DESIGN IMPLEMENTATION

During the realization of each of the components of the project, as well as the combination of
them into a single system, we met and overcame several unforeseen challenges. For instance, in
all of our analog design solutions we ran into the problems of long lead-time and obsoleted parts.
We spent much of our time searching for such parts and eventually found all of them from
various electronics surplus stores. Also, in some instances we were forced to compromise our
original objectives. We will now discuss these obstacles and changes in the same modular
manner as the previous section.

4.1 PREAMPLIFIER
During the initial testing of our preamplifier circuit, our largest concern was keeping its output
below a level that would cause clipping at the DSKs codec. To meet this challenge, we first
reduced the gain of the equalizers output by decreasing the feedback resistance of the summing
op-amp circuit. This brought the output to a manageable level, but we also found that adjustment
of the resonance potentiometer could still swing the output above the desired voltage. Therefore,
we decided to remove this resonance control by replacing its potentiometer with a static resistor
which kept the output below the necessary level. Consequently, this fixed the shape of the
middle frequency filter and slightly decreased the users ability to control the final preamplifier
output.

4.2 DIGITAL EFFECTS
We mentioned above that we used the DSKs DIP switch to select between the different effects
that we implemented, but this was not part of our original plan. Optimally, we wanted to connect
a front panel rotary switch to the four external interrupt pins available to the DSP and use it to
select the desired effect. However, after learning about the capabilities of this DIP switch we
decided to trade this front panel switching ability for the reduction of development time that
came with using the DSKs predefined functions. This allowed us more time to focus on writing
the actual effects algorithms, while maintaining the top-level goal of switching between effects.

11
We also ran into a major design and code-debugging problem while listening to the output of the
effects algorithms. While we designed the amplifier for a single channel, the DSKs codec
allowed only stereo (two-channel) input and output. We realized this problem during the
debugging of our variable delay effects, which created audible artifacts even with no input
applied, since every other iteration of our effects loops acted on a single channel. We solved this
problem by modifying our code to read two samples (left channel followed by right channel) for
every loop iteration, then throw away one sample in a temporary variable, and finally output the
processed channel twice. This was an acceptable solution since the preamplifier circuit allows
only one channel through and thus both channels going to the DSKs stereo input jack are always
identical.

About halfway through the project timeline, we realized that we faced the inconvenient problem
that the effects code needed to be downloaded to the DSP via the DSKs USB interface each
time we powered up the system. As a result, we added the additional goal to our project of being
able to load the program code from the DSKs onboard flash memory at its startup time. We did
not complete this sizeable objective since we did not allot time for it in our original timeline.
However, we did learn that our final executable code takes up only 128 kbytes of the available
256 kbytes of flash memory, and thus we know this objective is possible and we definitely plan
on implementing it in the future.

4.3 POWER AMPLIFIER
In order to test the power amplifier, we connected the output to an eight-ohm power resistor that
served as a temporary model for a speaker. During preliminary low-power testing, the power
amplifier circuit performed as expected. However, after a lengthy full-power test, the output
became increasingly distorted. We eventually found that the biasing potentiometer in the output
stage had failed and concluded that the power rating of this component was not adequate for the
high currents possible during maximum output. To solve this problem, we replaced the faulty
potentiometer with a higher-rated equivalent component. In addition, to implement the
necessary volume control, we designed and constructed a simple op-amp circuit with a
potentiometer in the feedback path that allows the maximum output of the DSK to represent the
maximum output of the power amplifier.
12
4.4 POWER SUPPLY
During the initial conception of the power supply design, we intended to use voltage regulators
to decrease the power amplifiers voltage rails to a level that the op-amp circuitry could use.
Unfortunately, after calculating the required voltages needed by the power amplifier, we found
that there were no regulators easily obtainable that could handle these large voltages. To resolve
this dilemma, we purchased another transformer with the appropriate output voltages and used a
diode bridge rectifier circuit to produce the acceptable DC voltage. Realizing that the DSK was
our must expensive and sensitive component of our amplifier system, we made the decision to
use the power supply provided with and tailored to the DSK, instead of our own. This choice
compromised our goal of using a single cord to power the system, but we felt that the risk of
damaging the DSK was much greater than reward of achieving this minor project goal.

4.5 AMPLIFIER SYSTEM ENCLOSURE
The main challenge we met while constructing the amplifier system enclosure was caused by a
misjudgment of material capabilities. We initially cut pieces of plexiglass for the top and front
panel of the enclosure, and planned on drilling large holes in the front panel piece for the
potentiometer controls. However, the plexiglass was too thin for the hole size necessary, and we
ended up shattering our front panel. Rather than purchase a new piece of plexiglass, we replaced
the it with a sturdy piece of cardboard of the same thickness and hence compromised the feature
of a see-through front panel.

5.0 TEST AND EVALUATION

There are two main ways to measure the performance of our amplifier system. Probably the
most obvious and important method of evaluation simply asks the highly subjective question:
does it sound good? After taking this final listening test, we would answer that question with an
overwhelming yes. We did not notice any distortion, and the frequency controls and digital
effects behaved as we expected. However, everyone perceives sound differently and therefore
this test has little, if any, objective validity. Taking this into account, we performed a few
quantitative tests on the system that provide the specifications which are standard in evaluating
13
similar products in the audio industry. Below we will explain the procedures for these tests and
the subsequent data that we collected from them.

5.1 FREQUENCY RESPONSE
The frequency response of an amplifier is perhaps the most telling determination of its ability to
reproduce an input signal with high fidelity. The optimum response would be a perfectly
horizontal line extending across the entire audio spectrum. Our measurements were complicated
by the fact that the signal passes through a parametric equalizer which is designed to deviate
from a flat response. To get around this we set the potentiometer controls to the resistances that
produced the flattest modeled response. Then, using a medium power output and a one Volt
PP

sine wave input, we took 11 octave band measurements from 20 Hz to 20 kHz and calculated the
frequency response in decibels. Additionally, we bypassed the digital effects for this
measurement in order to isolate the analog amplifier system response. The results that we
obtained are shown below.

Frequency Response with 7 Vrms Output, 0.707 Vrms Input
0
1
2
3
4
5
6
7
8
10 100 1000 10000 100000
Frequency (Hz)
2
0
*
l
o
g
(
V
o
u
t

/

V
i
n
)

Figure 3. Frequency Response of the Amplifier System

From this plot, it is apparent that our system did not produce the completely flat response we
desired, although we are pleased with the middle and high frequency response. Also, the roll-off
14
at low frequencies, which is approximately five decibels, is hardly audible to the average
listener. We speculate that the incorrect tuning of our parametric equalizer caused this less than
perfect response. In retrospect, we believe we should have directly measured the frequency
response of the power amplifier alone, since the equalizers main function is to alter this
response.

5.2 TOTAL HARMONIC DISTORTION
A consumer would be hard-pressed to find a modern audio amplifier on the market that did not
specify THD on its datasheet, as this is an industry-wide standard for determining amplifier
quality. THD measurements are commonly made with a 1 kHz input signal at several different
output power levels [7, pp. 30-31]. Following this industry standard, we took THD
measurements of our analog amplifier system at three different levels.

We used a Stanford Research Systems SR780 Spectrum Analyzer to make these measurements.
This analyzer has a built-in function for making THD measurements, which calculates the total
power level in the first five harmonic of a given fundamental frequency and expresses it as a
percentage of the power in the fundamental. The SR780 is a relatively old machine and only
saves data (not screenshots) to a disk in its own special format that cannot be viewed using
modern software. Therefore, we converted this data to ASCII format using software available to
download on the Stanford Research Systems website [8] and plotted it in Excel. The resulting
graph for our medium-power measurement can be seen in Figure 4 on the next page. We
measured the following THD values for our three output voltage levels: 0.10 % at one Volt
RMS
,
0.06 % at seven Volts
RMS
, and 0.09 % at 22 Volts
RMS
. Each of these figures is well below our
target of less than one percent THD, and hence we exceeded this project goal.

5.3 DIGITAL FILTER IMPULSE RESPONSES
Audio effects in general are especially susceptible to subjective measurement as the only true
way to evaluate a complex effects quality is by listening to it. However, we can at least describe
a digital filter uniquely by its impulse response and then compare it to a theoretically predicted
response as a means of evaluating its validity. Extracting an impulse response from a DSP in
real-time is not trivial, although the debugging capabilities of CCS make it possible.
15
THD Measurement @ 1 kHz, 7 Vrms Output, 0.707 Vrms Input
-120
-100
-80
-60
-40
-20
0
20
40
0 5000 10000 15000 20000 25000
Frequency (Hz)
V
o
l
t
a
g
e

O
u
t
p
u
t

(
d
B
)

Figure 4. Medium-Power THD Measurement

We modified CCS-to-MATLAB data transfer utilities written by Svetoslav Nikolov at the
Technical University of Denmark in order to convert time domain impulse responses from CCS
data files to MATLAB arrays [9]. This included modifying a General Extension Language
(GEL) script to save a buffer from the DSKs RAM into a data file to be read by these MATLAB
script utilities, along with writing our own MATLAB script to take the Fourier transform of the
data and plot the time and frequency domain impulse responses. The code for these utilities is
given in Appendix D.

To create and save the filter impulse responses, we used the CCS breakpoint and watch window
capabilities to stop the program at the appropriate time and insert a Dirac delta impulse into the
input buffer. Then we started the program and stopped it again to save the circular output buffer
to a data file before it filled up using the GEL menu command that we created. First we will
show the results for an FIR echo effect with a delay time of one-tenth of a second. The time
domain impulse response is shown in Figure 5 on the following page. The initial impulse and
echo can clearly be seen, and taking the Fourier transform of this yields the frequency domain
impulse response also given on the following page, in Figure 6.

THD = 0.06 %
16

Figure 5. FIR Echo Time Domain Impulse Response


Figure 6. FIR Echo Frequency Domain Impulse Response
17
The frequency response of a simple delay effect is commonly known as a comb filter, in which
the teeth of the comb appear at integer multiples of one divided by the delay time [3, p. 437].
In our example, this corresponds to teeth at integer multiples of one over one-tenth, which equals
ten. The frequency response shown clearly follows this predicted response, and thus proves the
validity of the effect.

As an effect becomes more complex, its impulse response becomes harder to predict. However,
we can still see what happens to the impulse response of a delay-based filter when we add
feedback or vary the delay time dynamically, as with flange and chorus effects. The time and
frequency domain impulse responses that we measured from the first flanging effect that we
implemented are given below, in Figures 7 and 8 (next page), respectively.


Figure 7. Flange Time Domain Impulse Response

The IIR nature of the effect can be observed from the time domain data, as the impulse slowly
dies away according to the specified decay factor. The frequency domain data shows a radical
change from the comb filter given by the echo. This is because the teeth of the comb are actually
18

Figure 8. Flange Frequency Domain Impulse Response

sweeping up and down the spectrum as the delay time changes, which cancels out the main comb
structure and introduces the high frequency artifacts that can be seen and which give the effect its
characteristic whooshing sound.

Finally, we will look at the frequency impulse response of the reverb filter, shown in Figure 9 on
the following page. One can immediately tell that the effect is less prevalent than the previous
two shown, as the frequency response resembles a sinc-like function. The parallel FIR echoes of
the effect along with the feedback work to cancel and smooth out the teeth of the comb filter.
However, this effect attempts to simulate a real medium-sized rooms impulse response, and it
obviously is too smooth to replicate such a complex function. In fact, a better way to implement
reverb, which is beyond the scope of this project, is to reverse the process we have taken by first
measuring a rooms impulse response, and then using it to design a filter to convolve with an
input signal [10, p. 393].

19

Figure 9. Reverb Frequency Domain Impulse Response

6.0 TIME AND COST CONSIDERATIONS

Throughout the entire process of designing and constructing our amplifier system, there were
several delays that made us question whether we would complete this project within the allotted
time. Long lead-times and hard to find parts often kept us from starting the construction of
important system sections on time, however, due to the aforementioned modularity of our
project design, we were able to continue working, and in some cases, get ahead of schedule in
the construction of other components. In addition, many unforeseen problems hindered our
progress such as the necessary modifications to the resonance portion of the equalizer and
correcting the erroneous outputs caused by the stereo codec. Fortunately, we received all of our
parts and solved the numerous problems with enough time to complete and demonstrate our final
product by the open house deadline.

From the time of our initial project proposal, we were well aware that this would be an expensive
undertaking. However, since this senior project is a culmination of all the knowledge we have
20
gained at The University of Texas and will be used for many years to come, we felt that these
costs were well justified. Table 2 and Table 3, shown below, detail the final cost of our amplifier
and our initially proposed budget, respectively. As can be seen from these tables, we spent more
than the initially proposed budget. The unexpectedly high price of our transformer and the fact
that many components have to be purchased in relatively large quantities played a major part in
the project being over budget. Also, if we would not have received such a substantial discount
on the DSK from the TI University Relations Team, we would have been extremely over budget.
We feel that our apparent budget problem is due to an underestimate of the cost during the
proposal and was not caused by mistakes made during the design and construction phases of the
project.

Table 2. Itemized Budget for the Entire Amplifier System

Component Cost
Preamp $ 63.00
DSK $ 295.00
Power Amplifier $ 50.00
Power Supply $ 195.00
Enclosure $ 50.00
Total $ 653.00


Table 3. Initially Proposed Budget for the Entire Project

Component Cost
TI TMS320C6713 DSK $ 395.00
Power Transformer $ 90.00
Resistors, Capacitors, Op-Amps, and other miscellaneous components $ 75.00
Amplifier Enclosure $ 50.00
Total $ 610.00

7.0 SAFETY ASPECTS OF DESIGN

Initially there were a few safety hazards regarding our project. However, we took several steps
to reduce the probability of any accidents occurring. In order to protect the user of the amplifier
system from any electrical dangers, we created the rugged enclosure that restricts access to all
circuitry. We also installed a warning LED, which signifies that the power is on. The wall outlet
was also protected from overloading using fuses and proper electrical taping around bare wire.
21
Even though the design and construction of our amplifier system will in no way advance
humanity, it is definitely safe and can provide the entertainment of listening to a quality audio
reproduction.

8.0 CONCLUSIONS AND RECOMMENDATIONS

In this report, we have presented a complete record of a semester of intense yet rewarding work.
First, we thoroughly defined our project in terms of what we initially planned to achieve and how
we premeditated our modular approach. Then, we discussed the steps we took and the
alternatives we considered in deciding on our final design solution. Many times during the
semester, we faced unforeseen challenges and we detailed our solutions to these obstacles and
how we compromised a number of our initial objectives. Finally, we presented the results of the
evaluation of our final product and compared them to our original expectations.

Although we attempted to meet every specification set forth in our original proposal, we fell
short of our objectives in a few respects. Among these were the slight decrease in user control
over our parametric equalizer, along with the absence of a front panel effects selector switch.
We also conceded our initial objective to have a single power plug for the entire system, as well
as the added objective of loading the effects into the DSP from flash memory at startup. Finally,
we destroyed our original plan for a plexiglass front panel on the enclosure and settled for a
temporary replacement. These shortcomings are definitely disappointing, but we feel that none
of them are detrimental to the major goals of the project.

In spite of these deficiencies, we also exceeded several of our project goals. The most notable of
these was surpassing our original one percent THD goal by an entire order of magnitude. We
also completed six different digital effects in time for the final demonstration, rather than the
four effects we initially specified. In addition, our final parametric equalizer had greater tonal
control ability than the standard equalizer we first envisioned. In our opinion, these
accomplishments alone have justified our efforts, although we believe that there is room for
improvement.

22
We have several plans for future improvements to the project. Even though most of these
enhancements seek to correct the shortcomings mentioned above, we also feel that without strict
deadlines we may be able to create new applications for our project that we have not yet thought
of. As shown in Figure 10 below, even the most complex of our digital effects, reverb, uses less
than 53 % of the DSPs available resources. Hopefully we can design more complex and
innovative effects in the future to maximize the projects potential.

Idle Flange Reverb Echo Initialization
CPU % vs. Time

Figure 10. DSP CPU Load Graph For Different Effects

In the beginning of this report, we mentioned that we had high expectations going into this
project. Not only do we feel like we met or exceeded those expectations, but we also had fun
doing so. We proved to ourselves that we have learned the necessary skills over our college
careers to undertake such a large and diverse project, and we are proud of our performances.
Best of all, we will be able to enjoy this project for many years to come.








23
REFERENCES

[1] W. Jung, Audio IC Op-Amp Applications, Howard W. Sams & Co., Indianapolis, Ind.,
1982.

[2] C. Anderton, Electronic Projects for Musicians, Amsco Publications, New York, 1975.

[3] C. Roads, The Computer Music Tutorial, MIT Press, Cambridge, Mass., 1996.

[4] C. Anderton, Multieffects for Musicians, Amsco Publications, New York, 1995.

[5] C. Dodge and T. Jerse, Computer Music: Synthesis, Composition, and Performance,
Thomson Learning, New York, 1997.

[6] R. Slone, High-Power Audio Amplifier Construction Manual, McGraw-Hill, New York,
1999.

[7] R. Slone, The Audiophiles Project Sourcebook, McGraw-Hill, New York, 2002.

[8] Stanford Research Systems Software Downloads, http://www.srsys.com/downloads/
soft.htm (current Nov. 29, 2004).

[9] 31611 Real Time Signal Processing Tools, http://www.oersted.dtu.dk/31611/?Tools/
main.html (current Nov. 30, 2004).

[10] F. Moore, Elements of Computer Music, Prentice-Hall, Englewood Cliffs, N.J., 1990.

A-1








APPENDIX A SCHEMATICS























A-2
APPENDIX A SCHEMATICS



Preamplifier Equalizer Schematic

A-3


Power Amplifier Schematic

B-1








APPENDIX B DIGITAL EFFECTS CODE

B-2
APPENDIX B DIGITAL EFFECTS CODE


/* Jason Keller and Joel Koepke
* EE464H Honors Senior Design Project: Audio Amp with Digital Effects
* The University of Texas at Austin, ECE Department
* TA: Yaoqing Yang Faculty Sponsor: Brian Evans
* 11/21/04
*
* ======== final_effects.c ========
*
* This code is adapted from Spectrum Digital's original "dsk_app" example
*/


/************************************************************************************
*************************** HEADER FILES ******************************************
***********************************************************************************/

#include "final_effectscfg.h"

#include <std.h>
#include <stdlib.h>
#include <math.h>
#include <swi.h>
#include <log.h>
#include <c6x.h>
#include <csl.h>
#include <csl_edma.h>
#include <csl_irq.h>
#include <csl_mcbsp.h>

// 6713 DSK Board Support Library header files
#include "dsk6713.h"
#include "dsk6713_led.h"
#include "dsk6713_dip.h"
#include "dsk6713_aic23.h"


/************************************************************************************
*************************** GLOBAL DECLARATIONS ********************************
***********************************************************************************/

// Function prototypes
void initIrq(void);
void initMcbsp(void);
void initEdma(void);
void processBuffer(void);
void processBufferFIREcho(void);
void processBufferIIREcho(void);
void processBufferFlange1(void);
void processBufferFlange2(void);
void processBufferChorus1(void);
void processBufferReverb1(void);
void edmaHwi(void);

B-3

// Constants for the buffered ping-pong transfer
#define BUFFSIZE 1024
#define PING 0
#define PONG 1

// Other constants
#define NDELBUFF 60000 //delay buffer length
#define LFOLEN1 64000 //LFO array length; LFO freq = fs/LFOLEN1
#define LFOLEN2 5512 //LFO array length; LFO freq = fs/LFOLEN1
#define pi 3.141592653589

Int16 gBufferXmtPing[BUFFSIZE]; // Transmit PING buffer
Int16 gBufferXmtPong[BUFFSIZE]; // Transmit PONG buffer

Int16 gBufferRcvPing[BUFFSIZE]; // Receive PING buffer
Int16 gBufferRcvPong[BUFFSIZE]; // Receive PONG buffer

EDMA_Handle hEdmaXmt; // EDMA channel handles
EDMA_Handle hEdmaReloadXmtPing;
EDMA_Handle hEdmaReloadXmtPong;
EDMA_Handle hEdmaRcv;
EDMA_Handle hEdmaReloadRcvPing;
EDMA_Handle hEdmaReloadRcvPong;

MCBSP_Handle hMcbsp1; // McBSP1 (codec data) handle

Int16 gXmtChan; // TCC codes (see initEDMA())
Int16 gRcvChan;


/*
* EDMA Config data structure
*/

// Transmit side EDMA configuration
EDMA_Config gEdmaConfigXmt = {
EDMA_FMKS(OPT, PRI, HIGH) | // Priority
EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size
EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source?
EDMA_FMKS(OPT, SUM, INC) | // Src update mode
EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest
EDMA_FMKS(OPT, DUM, NONE) | // Dest update mode
EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt?
EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code
EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters?
EDMA_FMKS(OPT, FS, NO), // Use frame sync?

(Uint32)&gBufferXmtPing, // Src address

EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count
EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count

EDMA_FMKS(DST, DST, OF(0)), // Dest address

EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value

B-4
EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value

EDMA_FMK (RLD, ELERLD, NULL) | // Reload element
EDMA_FMK (RLD, LINK, NULL) // Reload link
};

// Receive side EDMA configuration
EDMA_Config gEdmaConfigRcv = {
EDMA_FMKS(OPT, PRI, HIGH) | // Priority
EDMA_FMKS(OPT, ESIZE, 16BIT) | // Element size
EDMA_FMKS(OPT, 2DS, NO) | // 2 dimensional source?
EDMA_FMKS(OPT, SUM, NONE) | // Src update mode
EDMA_FMKS(OPT, 2DD, NO) | // 2 dimensional dest
EDMA_FMKS(OPT, DUM, INC) | // Dest update mode
EDMA_FMKS(OPT, TCINT, YES) | // Cause EDMA interrupt?
EDMA_FMKS(OPT, TCC, OF(0)) | // Transfer complete code
EDMA_FMKS(OPT, LINK, YES) | // Enable link parameters?
EDMA_FMKS(OPT, FS, NO), // Use frame sync?

EDMA_FMKS(SRC, SRC, OF(0)), // Src address

EDMA_FMK (CNT, FRMCNT, NULL) | // Frame count
EDMA_FMK (CNT, ELECNT, BUFFSIZE), // Element count

(Uint32)&gBufferRcvPing, // Dest address

EDMA_FMKS(IDX, FRMIDX, DEFAULT) | // Frame index value
EDMA_FMKS(IDX, ELEIDX, DEFAULT), // Element index value

EDMA_FMK (RLD, ELERLD, NULL) | // Reload element
EDMA_FMK (RLD, LINK, NULL) // Reload link
};

// McBSP codec data channel configuration
static MCBSP_Config mcbspCfg1 = {
MCBSP_FMKS(SPCR, FREE, NO) |
MCBSP_FMKS(SPCR, SOFT, NO) |
MCBSP_FMKS(SPCR, FRST, YES) |
MCBSP_FMKS(SPCR, GRST, YES) |
MCBSP_FMKS(SPCR, XINTM, XRDY) |
MCBSP_FMKS(SPCR, XSYNCERR, NO) |
MCBSP_FMKS(SPCR, XRST, YES) |
MCBSP_FMKS(SPCR, DLB, OFF) |
MCBSP_FMKS(SPCR, RJUST, RZF) |
MCBSP_FMKS(SPCR, CLKSTP, DISABLE) |
MCBSP_FMKS(SPCR, DXENA, OFF) |
MCBSP_FMKS(SPCR, RINTM, RRDY) |
MCBSP_FMKS(SPCR, RSYNCERR, NO) |
MCBSP_FMKS(SPCR, RRST, YES),

MCBSP_FMKS(RCR, RPHASE, SINGLE) |
MCBSP_FMKS(RCR, RFRLEN2, DEFAULT) |
MCBSP_FMKS(RCR, RWDLEN2, DEFAULT) |
MCBSP_FMKS(RCR, RCOMPAND, MSB) |
MCBSP_FMKS(RCR, RFIG, NO) |
MCBSP_FMKS(RCR, RDATDLY, 0BIT) |

B-5
MCBSP_FMKS(RCR, RFRLEN1, OF(1)) |
MCBSP_FMKS(RCR, RWDLEN1, 16BIT) |
MCBSP_FMKS(RCR, RWDREVRS, DISABLE),

MCBSP_FMKS(XCR, XPHASE, SINGLE) |
MCBSP_FMKS(XCR, XFRLEN2, DEFAULT) |
MCBSP_FMKS(XCR, XWDLEN2, DEFAULT) |
MCBSP_FMKS(XCR, XCOMPAND, MSB) |
MCBSP_FMKS(XCR, XFIG, NO) |
MCBSP_FMKS(XCR, XDATDLY, 0BIT) |
MCBSP_FMKS(XCR, XFRLEN1, OF(1)) |
MCBSP_FMKS(XCR, XWDLEN1, 16BIT) |
MCBSP_FMKS(XCR, XWDREVRS, DISABLE),

MCBSP_FMKS(SRGR, GSYNC, DEFAULT) |
MCBSP_FMKS(SRGR, CLKSP, DEFAULT) |
MCBSP_FMKS(SRGR, CLKSM, DEFAULT) |
MCBSP_FMKS(SRGR, FSGM, DEFAULT) |
MCBSP_FMKS(SRGR, FPER, DEFAULT) |
MCBSP_FMKS(SRGR, FWID, DEFAULT) |
MCBSP_FMKS(SRGR, CLKGDV, DEFAULT),

MCBSP_MCR_DEFAULT,
MCBSP_RCER_DEFAULT,
MCBSP_XCER_DEFAULT,

MCBSP_FMKS(PCR, XIOEN, SP) |
MCBSP_FMKS(PCR, RIOEN, SP) |
MCBSP_FMKS(PCR, FSXM, EXTERNAL) |
MCBSP_FMKS(PCR, FSRM, EXTERNAL) |
MCBSP_FMKS(PCR, CLKXM, INPUT) |
MCBSP_FMKS(PCR, CLKRM, INPUT) |
MCBSP_FMKS(PCR, CLKSSTAT, DEFAULT) |
MCBSP_FMKS(PCR, DXSTAT, DEFAULT) |
MCBSP_FMKS(PCR, FSXP, ACTIVEHIGH) |
MCBSP_FMKS(PCR, FSRP, ACTIVEHIGH) |
MCBSP_FMKS(PCR, CLKXP, FALLING) |
MCBSP_FMKS(PCR, CLKRP, RISING)
};

// Codec configuration settings
DSK6713_AIC23_Config config = { \
0x0017, /* 0 DSK6713_AIC23_LEFTINVOL Left line input channel volume */ \
0x0017, /* 1 DSK6713_AIC23_RIGHTINVOL Right line input channel volume */\
0x01F9, /* 2 DSK6713_AIC23_LEFTHPVOL Left channel headphone volume */ \
0x01F9, /* 3 DSK6713_AIC23_RIGHTHPVOL Right channel headphone volume */ \
0x0012, /* 4 DSK6713_AIC23_ANAPATH Analog audio path control */ \
0x0001, /* 5 DSK6713_AIC23_DIGPATH Digital audio path control; x0005 for 44.1kHz Digital De-Emphasis
*/ \
0x0002, /* 6 DSK6713_AIC23_POWERDOWN Power down control */ \
0x0043, /* 7 DSK6713_AIC23_DIGIF Digital audio interface format */ \
0x0023, /* 8 DSK6713_AIC23_SAMPLERATE Sample rate control; x0023 for 44.1kHz, x0001 for 48kHz */
\
0x0001 /* 9 DSK6713_AIC23_DIGACT Digital interface activation */ \
};


B-6
float inBuff[NDELBUFF]; // input delay buffer
float outBuff[NDELBUFF]; // output delay buffer
Uint16 delaySamps; // # of samples to delay by
float decay; // decay factor for echo
float scale; // scale factor (1/max output) to avoid clipping
Uint16 LFOsin[LFOLEN1]; // LFO sine wave array; varies delay time
Uint16 LFOtri[LFOLEN1]; // LFO triangle wave array; varies delay time
Uint16 LFOtri2[LFOLEN2]; // faster LFO triangle wave array; varies delay time
//Uint16 LFOrand[LFOLEN2]; // LFO triangle wave array

/************************************************************************************
*************************** MAIN FUNCTION ****************************************
***********************************************************************************/
/*
* main() - The main user task. Performs application initialization and
* starts the data transfer.
*/
void main()
{
Uint16 ii = 0;

/* Initialize Board Support Library */
DSK6713_init();

/* Initialize LEDs and DIP switches */
DSK6713_LED_init();
DSK6713_DIP_init();

/* Clear buffers */
memset((void *)gBufferXmtPing, 0, BUFFSIZE * 4 * 2);

for (ii = 0; ii < NDELBUFF; ii++ ){
inBuff[ii] = 0.0;
outBuff[ii] = 0.0;
}

/* Initialize LFOsin index lookup table */
for (ii = 0; ii < LFOLEN1; ii++ )
LFOsin[ii] = 880 + floor(50*sin(pi*ii/LFOLEN1));

/* Initialize LFOtri index lookup table */
for (ii = 0; ii < LFOLEN1/2; ii++ )
LFOtri[ii] = 40 + floor(620*2*ii/LFOLEN1);
for (ii = LFOLEN1/2; ii < LFOLEN1; ii++ )
LFOtri[ii] = 660 - floor(620*2*(ii-LFOLEN1/2)/LFOLEN1);

/* Initialize LFOtri2 index lookup table */
for (ii = 0; ii < LFOLEN2/2; ii++ )
LFOtri2[ii] = 40 + floor(620*2*ii/LFOLEN2);
for (ii = LFOLEN2/2; ii < LFOLEN2; ii++ )
LFOtri2[ii] = 660 - floor(620*2*(ii-LFOLEN2/2)/LFOLEN2);

/* Initialize LFOrand index lookup table
for (ii = 0; ii < LFOLEN2; ii++ )
LFOrand[ii] = 40 + rand(); */


B-7
AIC23_setParams(&config); // Configure the codec

initMcbsp(); // Initialize McBSP1 for audio transfers

IRQ_globalDisable(); // Disable global interrupts during setup

initEdma(); // Initialize the EDMA controller

initIrq(); // Initialize interrupts

IRQ_globalEnable(); // Re-enable global interrupts
}


/************************************************************************************
*************************** HELPER FUNCTIONS ***************************************
***********************************************************************************/

/*
* initMcbsp() - Initialize the McBSP for codec data transfers using the
* configuration define at the top of this file.
*/
void initMcbsp()
{
/* Open the codec data McBSP */
hMcbsp1 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);

/* Configure the codec to match the AIC23 data format */
MCBSP_config(hMcbsp1, &mcbspCfg1);

/* Start the McBSP running */
MCBSP_start(hMcbsp1, MCBSP_XMIT_START | MCBSP_RCV_START |
MCBSP_SRGR_START | MCBSP_SRGR_FRAMESYNC, 220);
}


/*
* initIrq() - Initialize and enable the DMA receive interrupt using the CSL.
* The interrupt service routine for this interrupt is edmaHwi.
*/
void initIrq(void)
{
/* Enable EDMA interrupts to the CPU */
IRQ_clear(IRQ_EVT_EDMAINT); // Clear any pending EDMA interrupts
IRQ_enable(IRQ_EVT_EDMAINT); // Enable EDMA interrupt
}


/*
* initEdma() - Initialize the DMA controller. Use linked transfers to
* automatically transition from ping to pong and visa-versa.
*/
void initEdma(void)
{
/* Configure transmit channel */

B-8
hEdmaXmt = EDMA_open(EDMA_CHA_XEVT1, EDMA_OPEN_RESET); // get hEdmaXmt handle and reset
channel
hEdmaReloadXmtPing = EDMA_allocTable(-1); // get hEdmaReloadXmtPing handle
hEdmaReloadXmtPong = EDMA_allocTable(-1); // get hEdmaReloadXmtPong handle

gEdmaConfigXmt.dst = MCBSP_getXmtAddr(hMcbsp1); // set the desination address to McBSP1 DXR

gXmtChan = EDMA_intAlloc(-1); // get an open TCC
gEdmaConfigXmt.opt |= EDMA_FMK(OPT,TCC,gXmtChan); // set TCC to gXmtChan

EDMA_config(hEdmaXmt, &gEdmaConfigXmt); // then configure the registers
EDMA_config(hEdmaReloadXmtPing, &gEdmaConfigXmt); // and the reload for Ping

gEdmaConfigXmt.src = EDMA_SRC_OF(gBufferXmtPong); // change the structure to have a source of Pong
EDMA_config(hEdmaReloadXmtPong, &gEdmaConfigXmt); // and configure the reload for Pong

EDMA_link(hEdmaXmt,hEdmaReloadXmtPong); // link the regs to Pong
EDMA_link(hEdmaReloadXmtPong,hEdmaReloadXmtPing); // link Pong to Ping
EDMA_link(hEdmaReloadXmtPing,hEdmaReloadXmtPong); // and link Ping to Pong

/* Configure receive channel */
hEdmaRcv = EDMA_open(EDMA_CHA_REVT1, EDMA_OPEN_RESET); // get hEdmaRcv handle and reset
channel
hEdmaReloadRcvPing = EDMA_allocTable(-1); // get hEdmaReloadRcvPing handle
hEdmaReloadRcvPong = EDMA_allocTable(-1); // get hEdmaReloadRcvPong handle

gEdmaConfigRcv.src = MCBSP_getRcvAddr(hMcbsp1); // and the desination address to McBSP1 DXR

gRcvChan = EDMA_intAlloc(-1); // get an open TCC
gEdmaConfigRcv.opt |= EDMA_FMK(OPT,TCC,gRcvChan); // set TCC to gRcvChan

EDMA_config(hEdmaRcv, &gEdmaConfigRcv); // then configure the registers
EDMA_config(hEdmaReloadRcvPing, &gEdmaConfigRcv); // and the reload for Ping

gEdmaConfigRcv.dst = EDMA_DST_OF(gBufferRcvPong); // change the structure to have a destination of
Pong
EDMA_config(hEdmaReloadRcvPong, &gEdmaConfigRcv); // and configure the reload for Pong

EDMA_link(hEdmaRcv,hEdmaReloadRcvPong); // link the regs to Pong
EDMA_link(hEdmaReloadRcvPong,hEdmaReloadRcvPing); // link Pong to Ping
EDMA_link(hEdmaReloadRcvPing,hEdmaReloadRcvPong); // and link Ping to Pong

/* Enable interrupts in the EDMA controller */
EDMA_intClear(gXmtChan);
EDMA_intClear(gRcvChan); // clear any possible spurious interrupts

EDMA_intEnable(gXmtChan); // enable EDMA interrupts (CIER)
EDMA_intEnable(gRcvChan); // enable EDMA interrupts (CIER)

EDMA_enableChannel(hEdmaXmt); // enable EDMA channel
EDMA_enableChannel(hEdmaRcv); // enable EDMA channel

/* Do a dummy write to generate the first McBSP transmit event */
MCBSP_write(hMcbsp1, 0);
}


B-9

/************************************************************************************
*************************** INTERRUPT SERVICE ROUTINES **************************
***********************************************************************************/

/*
* edmaHwi() - Interrupt service routine for the DMA transfer. It is
* triggered when a complete DMA receive frame has been
* transferred. The edmaHwi ISR is inserted into the interrupt
* vector table at compile time through a setting in the DSP/BIOS
* configuration under Scheduling --> HWI --> HWI_INT8. edmaHwi
* uses the DSP/BIOS Dispatcher to save register state and make
* sure the ISR co-exists with other DSP/BIOS functions.
*/
void edmaHwi(void)
{
static Uint32 pingOrPong = PING; // Ping-pong state variable
static Int16 xmtdone = 0, rcvdone = 0;

/* Check CIPR to see which transfer completed */
if (EDMA_intTest(gXmtChan))
{
EDMA_intClear(gXmtChan);
xmtdone = 1;
}
if (EDMA_intTest(gRcvChan))
{
EDMA_intClear(gRcvChan);
rcvdone = 1;
}

/* If both transfers complete, signal processBufferSwi to handle */
if (xmtdone && rcvdone)
{
if (pingOrPong==PING)
{
if (!DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & DSK6713_DIP_get(2) & DSK6713_DIP_get(3))
SWI_or(&processBufferFIREchoSwi, PING); // call FIR Echo function

else if (DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferIIREchoSwi, PING); // call IIR Echo function

else if (!DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferFlange1Swi, PING); // call Flange1 function

else if (DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) & DSK6713_DIP_get(3))
SWI_or(&processBufferFlange2Swi, PING); // call Flange2 function

else if (!DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferChorus1Swi, PING); // call Chorus1 function

else if (DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))

B-10
SWI_or(&processBufferReverb1Swi, PING); // call Reverb1 function

else
SWI_or(&processBufferSwi, PING); // bypass effects

pingOrPong = PONG;
} else
{
if (!DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & DSK6713_DIP_get(2) & DSK6713_DIP_get(3))
SWI_or(&processBufferFIREchoSwi, PONG); // call FIR Echo function

else if (DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & DSK6713_DIP_get(2) & DSK6713_DIP_get(3))
SWI_or(&processBufferIIREchoSwi, PONG); // call IIR Echo function

else if (!DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferFlange1Swi, PONG); // call Flange1 function

else if (DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) & DSK6713_DIP_get(3))
SWI_or(&processBufferFlange2Swi, PONG); // call Flange2 function

else if (!DSK6713_DIP_get(0) & DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferChorus1Swi, PONG); // call Chorus1 function

else if (DSK6713_DIP_get(0) & !DSK6713_DIP_get(1) & !DSK6713_DIP_get(2) &
DSK6713_DIP_get(3))
SWI_or(&processBufferReverb1Swi, PONG); // call Reverb1 function

else
SWI_or(&processBufferSwi, PONG); // bypass effects

pingOrPong = PING;
}
rcvdone = 0;
xmtdone = 0;
}
}


/************************************************************************************
*************************** THREADS ***********************************************
***********************************************************************************/

/*
* processBuffer functions - Process audio data once it has been received.
*/
void processBuffer(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
Int16 temp; // temp value to take right sample and trash it b/c this is mono

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

B-11

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = inBuff[j];

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = inBuff[j];

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

void processBufferFIREcho(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
Uint16 k = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

decay = 0.95;
scale = 0.5;

delaySamps = 4410;


B-12
/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + inBuff[k]*decay);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + inBuff[k]*decay);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

void processBufferIIREcho(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index

B-13
Uint16 k = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

decay = 0.9;
scale = 0.5;

delaySamps = 44100;

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + outBuff[k]*decay);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + outBuff[k]*decay);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}

B-14
}
}

void processBufferFlange1(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
static Uint16 l = 0; // static index to LFO array that varies delay time
Uint16 k = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

decay = 0.99;
scale = 0.5;

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOtri[l];
if (l < LFOLEN1-1) l++; //update LFO index
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + outBuff[k]*decay);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOtri[l];
if (l < LFOLEN1-1) l++; //update LFO index
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;


B-15
inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + outBuff[k]*decay);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

void processBufferFlange2(void) //actually vibrato
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
static Uint16 l = 0; // static index to LFO array that varies delay time
Uint16 k = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

float dry = 1.2;
decay = 0.7;
scale = 0.52;

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOtri2[l];
if (l < LFOLEN2-1) l++; //update LFO index
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j]*dry + outBuff[k]*decay);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample


B-16
gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOtri2[l];
if (l < LFOLEN2-1) l++; //update LFO index
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j]*dry + outBuff[k]*decay);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

void processBufferChorus1(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
static Uint16 l = 0; // static index to LFO array that varies delay time
Uint16 k = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

decay = 0.99;
scale = 0.5;

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOsin[l];
if (l < LFOLEN1-1) l++; //update LFO index

B-17
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + inBuff[k]*decay);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

delaySamps = LFOsin[l];
if (l < LFOLEN1-1) l++; //update LFO index
else l = 0;

if (j >= delaySamps) k = j - delaySamps; //Find delay index
else k = j - delaySamps + NDELBUFF;

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j] + inBuff[k]*decay);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

void processBufferReverb1(void)
{
Uint32 pingPong;
Uint16 i = 0; // index to EDMA buffer, PING or PONG
static Uint16 j = 0; // static index to circular delay buffers - current I/O index
Uint16 k1 = 0; // current delay index to circular delay buffers
Uint16 k2 = 0; // current delay index to circular delay buffers

B-18
Uint16 k3 = 0; // current delay index to circular delay buffers
Uint16 k4 = 0; // current delay index to circular delay buffers
Uint16 k5 = 0; // current delay index to circular delay buffers
Uint16 k6 = 0; // current delay index to circular delay buffers
Uint16 k7 = 0; // current delay index to circular delay buffers
Uint16 k8 = 0; // current delay index to circular delay buffers
Int16 temp; // temp value to take right sample and trash it b/c this is mono

float scale2 = 0.5;
float decay2 = 0.7;
float decay3 = 0.3;
Uint16 delaySamps1 = 706; //reverb time 1 = 16ms
Uint16 delaySamps2 = 882; //reverb time 2 = 20ms
Uint16 delaySamps3 = 1191; //reverb time 3 = 27ms
Uint16 delaySamps4 = 1411; //reverb time 4 = 32ms
Uint16 delaySamps5 = 1808; //reverb time 5 = 41ms
Uint16 delaySamps6 = 2029; //reverb time 6 = 46ms
Uint16 delaySamps7 = 2470; //feedback reverb time 1 = 56ms
Uint16 delaySamps8 = 3219; //feedback reverb time 2 = 73ms

scale = 0.167;

/* Get contents of mailbox posted by edmaHwi */
pingPong = SWI_getmbox();

/* Copy data from transmit to receive, process audio here */
if (pingPong == PING) {
/* Copy receive PING buffer to transmit PING buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps1) k1 = j - delaySamps1; //Find delay index
else k1 = j - delaySamps1 + NDELBUFF;
if (j >= delaySamps2) k2 = j - delaySamps2; //Find delay index
else k2 = j - delaySamps2 + NDELBUFF;
if (j >= delaySamps3) k3 = j - delaySamps3; //Find delay index
else k3 = j - delaySamps3 + NDELBUFF;
if (j >= delaySamps4) k4 = j - delaySamps4; //Find delay index
else k4 = j - delaySamps4 + NDELBUFF;
if (j >= delaySamps5) k5 = j - delaySamps5; //Find delay index
else k5 = j - delaySamps5 + NDELBUFF;
if (j >= delaySamps6) k6 = j - delaySamps6; //Find delay index
else k6 = j - delaySamps6 + NDELBUFF;
if (j >= delaySamps7) k7 = j - delaySamps7; //Find delay index
else k7 = j - delaySamps7 + NDELBUFF;
if (j >= delaySamps8) k6 = j - delaySamps8; //Find delay index
else k8 = j - delaySamps8 + NDELBUFF;

inBuff[j] = (float)gBufferRcvPing[i]; //get left sample

outBuff[j] = scale*(inBuff[j]*0.8 + inBuff[k1]*0.7 + inBuff[k2]*0.6 + inBuff[k3]*0.75 +
inBuff[k4]*0.55 + inBuff[k5]*0.8 + inBuff[k6]*0.7);
outBuff[j] = scale2*(outBuff[j] + outBuff[k7]*decay2 + outBuff[k8]*decay3);

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample

i++;

B-19

temp = (float)gBufferRcvPing[i]; //get right sample

gBufferXmtPing[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
} else {
/* Copy receive PONG buffer to transmit PONG buffer */
for (i = 0; i < BUFFSIZE; i++ ){

if (j >= delaySamps1) k1 = j - delaySamps1; //Find delay index
else k1 = j - delaySamps1 + NDELBUFF;
if (j >= delaySamps2) k2 = j - delaySamps2; //Find delay index
else k2 = j - delaySamps2 + NDELBUFF;
if (j >= delaySamps3) k3 = j - delaySamps3; //Find delay index
else k3 = j - delaySamps3 + NDELBUFF;
if (j >= delaySamps4) k4 = j - delaySamps4; //Find delay index
else k4 = j - delaySamps4 + NDELBUFF;
if (j >= delaySamps5) k5 = j - delaySamps5; //Find delay index
else k5 = j - delaySamps5 + NDELBUFF;
if (j >= delaySamps6) k6 = j - delaySamps6; //Find delay index
else k6 = j - delaySamps6 + NDELBUFF;
if (j >= delaySamps7) k7 = j - delaySamps7; //Find delay index
else k7 = j - delaySamps7 + NDELBUFF;
if (j >= delaySamps8) k6 = j - delaySamps8; //Find delay index
else k8 = j - delaySamps8 + NDELBUFF;

inBuff[j] = (float)gBufferRcvPong[i]; //get left sample

outBuff[j] = scale*(inBuff[j]*0.8 + inBuff[k1]*0.7 + inBuff[k2]*0.6 + inBuff[k3]*0.75 +
inBuff[k4]*0.55 + inBuff[k5]*0.8 + inBuff[k6]*0.7);
outBuff[j] = scale2*(outBuff[j] + outBuff[k7]*decay2 + outBuff[k8]*decay3);

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample

i++;

temp = (float)gBufferRcvPong[i]; //get right sample

gBufferXmtPong[i] = (Int16)outBuff[j]; //output left sample (forget right)

if (j < NDELBUFF-1) j++;
else j = 0;
}
}
}

/*
* blinkLED() - Periodic thread (PRD) that toggles LED #0 every 500ms if
* DIP switch #0 is depressed. The thread is configured
* in the DSP/BIOS configuration tool under Scheduling -->
* PRD --> PRD_blinkLed. The period is set there at 500
* ticks, with each tick corresponding to 1ms in real
* time.

B-20
*/
void blinkLED(void)
{
/* Turn on LED #0 if DIP switch #0 is off (depressed) */
if (!DSK6713_DIP_get(0))
DSK6713_LED_on(0);
else
DSK6713_LED_off(0);
/* Turn on LED #1 if DIP switch #1 is off (depressed) */
if (!DSK6713_DIP_get(1))
DSK6713_LED_on(1);
else
DSK6713_LED_off(1);
/* Turn on LED #2 if DIP switch #2 is off (depressed) */
if (!DSK6713_DIP_get(2))
DSK6713_LED_on(2);
else
DSK6713_LED_off(2);
/* Turn on LED #3 if DIP switch #3 is off (depressed) */
if (!DSK6713_DIP_get(3))
DSK6713_LED_on(3);
else
DSK6713_LED_off(3);
}

C-1












APPENDIX C PROJECT PICTURES

C-2
APPENDIX C PROJECT PICTURES


The Complete Amplifier System


The Complete Amplifier System Top View

C-3

The Amplifier System Front Panel


The Preamplifier

C-4

The DSK


The Power Amplifier

C-5

The Power Supply

D-1











APPENDIX D IMPULSE RESPONSE UTILITY CODE


































D-2
APPENDIX D IMPULSE RESPONSE UTILITY CODE



% file to read impulse response and plot it frequency response
% first must make 50000 element int32 array impulse response named "imp"
% using Nikolov's functions

fs = 44100;
X = 30000;
imp2 = double(imp(1:X));
tscale = (1/fs)*(1:X); %make time scale

figure(1)
plot(tscale,imp2); %plot time series impulse response
title('Time Domain Impulse Response');
xlabel('Time (seconds)');
ylabel('Amplitude');

N = 32768;
fftimp2 = fft(imp2,N); %do fft
fftimp2 = fftshift(fftimp2);
fftimp2 = abs(fftimp2((N/2+1):N)); %get absolute positive frequency values
fftimp2 = fftimp2/max(fftimp2); %normalize output

fscale = 0:(fs/N):(fs/2-1); %make frequency scale

figure(2)
plot(fscale(1:100),fftimp2(1:100));
title('Frequency Domain Impulse Response');
xlabel('Frequency (Hz)');
ylabel('Normalized magnitude');



MATLAB Utility to Plot Impulse Responses












D-3
/*
* The menu item "Signal Options" will appear under the main menu GEL:
* GEL>Signal Options
*/
menuitem "Signal Options"

/*
* The function save_signal_to_file() will dump the
* memory content, starting at the address indicated by
* the label "buffer". It will save 50000 32-bit words
* from the data-memory (type 1), to the file "impulse_response.dat".
*/
hotmenu save_signal_to_file()
{
GEL_MemorySave(outBuff, 1, 50000, "impulse_response.dat");
}


GEL Script to Save Data Buffer From CCS

S-ar putea să vă placă și