Professional Documents
Culture Documents
Audio Effect: Haas Delay
Christopher Hogan & PJ O’Sullivan
Final Report ENGS 31
2
Abstract
The haas delay effect is a sound engineering technique used to increase a track’s width in the
stereo field of a mix. Our device receives 12bit mono audio and outputs 12bit stereo audio.
With two buttons, the user controls the delay amount, reflected in ms on the device’s display. The
incoming audio is duplicated into a left and right channel, and the resulting right channel is
delayed by the specified amount before output, creating the audible haas effect.
3
Table of Contents
1. Introduction 4
2. Design Solution 4
2.1. Specifications 4
2.2. Operating Instructions 5
2.3. Theory of O
peration 5
2.4. Construction and Debugging 8
3. Evaluation 9
4. Conclusions 10
5. Acknowledgements 10
6. References 11
7. Appendices 12
7.1. Appendix A: Front Panel
7.2. Appendix B: Block Diagrams
7.3. Appendix C: State Diagrams
7.4. Appendix D: Simulation Waveforms
7.5. Appendix E: Parts List
7.6. Appendix F: VHDL Code
7.7. Appendix G: VHDL Testbench Code
7.8. Appendix H: Resource Utilization
7.9. Appendix I: Analysis of Residul Warnings
7.10. Appendix J: Datasheets
4
1. Introduction
Our project was to create a hardware implementation of haas delay, an integral production
technique in contemporary sound engineering. The haas effect as implemented here involves
taking a mono input signal, duplicating it, and delaying one of the resulting channels by a small
amount, creating the illusion of distance attenuation. This illusion makes the signal appear to be
emanating from multiple sources surrounding you, affording the sound a much wider space in the
stereo field. By gradually increasing the intensity of the effect through incrementation of the
delay time, the user is able to better understand the nature of this omnipresent yet often subtle
effect.
2. Design Solution
2.1. Specifications
Our design takes an auxiliary audio input and routes it through a transformer, balancing the audio
and translating only the left channel, resulting in a 12bit mono audio signal that is then routed
into the FPGA via a dualRCA port and a PMOD AD1. The amount of haas delay implemented
is a user selected amount from 0 to 20ms than can be incremented or decremented by pressing an
display. The processed audio is output from the board in stereo through two dual_RCA ports and
two PMOD DA2’s before being funneled through another transformer and into headphones via a
TRS quarter inch output. T
hus, an audio source and two buttons are required for input, and a
display engine and headphones are required for output. See Appendices A and B for more detail
5
2.2. Operating Instructions
● Connect a Basys 3 FPGA (with a PMOD AD1, two PMOD DA2’s, and respective RCA
ports connected) and program the haas bitstream. Ensure that the off board components
(transformers and necessary audio connections) are assembled properly. See Appendix A
converted from the RCA outputs of the postDAC transformer. You should hear
undistorted audio when your source plays. If the output is clipping, turn down the volume
of the input.
○ Note: The haas delay effect is best demonstrated using simpler signals (e.g. single
instruments, pure tones) than complex ones (e.g. full band recordings). Further,
haas delay is most easily observed using headphones. If you choose to connect
speakers instead, make sure to use two and spread them apart at least four feet.
● Use the up and down buttons on the Basys 3 to control the amount of haas delay affecting
your input. The startup default is the maximum amount, 20ms, of delay. 0ms of delay is
the minimum amount, effectively turning off the haas effect.
2.3. Theory of O
peration
Our device takes a mono audio signal and channels it through an analog to digital converter,
converting serial bits in to parallel vectors out. The single 12bit std_logic_vector output from
the ADC is then split into two signals; the first runs directly to the left channel digital to analog
converter, and the second runs into the haas engine, the source of our delay. The haas engine
enacts delay by continuously writing the input data to a dual ported RAM with a simple 11bit
6
write address counter and reading previously written bits according to desired delay time.
Desired delay time is defaulted to a maximum 20ms and controlled from there by two input
buttons, up and down. These inputs cause state changes within the b
uttons
controller,
updating the delay amount sent to the haas engine’s subtractor for figuring which RAM address
will be read. The 12bit output d
ata_bus_out
from the haas engine is connected to the input
of the right channel digital to analog converter. Each DAC takes 12bit vector inputs and outputs
a stream of serial information through two PMOD DA2’s, creating stereo imaged audio with
haas delay.
ADC Block
The Analog to Digital Converter block takes in two streams of single bit audio information from
the balanced (positive channel and negative channel) mono input v ia the PMOD AD1. Our
sample rate trigger t
ake_sample_sig
activates a load cycle 44,100 times per second, each
cycle taking a series of input bits. Each load cycle is fifteen counts as dictated in the ADC state
machine, taking the incoming bit information (ignoring three prefix bits) and sending it to the
ADC shift register. The shift register loads and shifts twelve bits, producing 12bit
std_logic_vectors to be passed along to ADC out registers. Before output, the ADC subtracts the
power supply noise.
Haas Engine Block
The haas engine block uses a counter, a dual ported ram, and a subtractor to intake 12bit vectors
and output them after a specified delay time. The counter increments from 0 to 1023 and writes
incoming information into the dual ported ram, instantiated as a 1024 address array of 12bit
7
vectors. The block takes in d
elay_amount
f rom the controller and feeds it to the subtractor,
which subtracts the number of addresses correlating with desired delay Y from the current write
address, providing a read address that outputs the vector from Y ms ago.
DAC Block
Two D
AC’s are instantiated, one for stereo left output and one for stereo right output. The DAC’s
serve the opposite function of the ADC’s, taking in 12bit std_logic_vectors and outputting a
serial stream of bits to PMOD DA2 headers using shift registers. Before input to the DAC shift
registers, incoming vectors are duplicated. One of the two vectors is inverted, yielding one
positive and one negative vector for balanced output to each channel’s RCA ports. 1024 is added
to both vectors (through a cast to unsigned and back) to account for the earlier balancing and DC
offset, and both vectors are affixed with two prefix bits: “00”. These 14bit vectors are passed
into the DAC shift registers once every t
ake_sample_sig
assertion before the latter 12bits
are shifted out serially according to the 15 count cycle as detailed by the DAC state machine.
Controller: Delay Buttons
The controller keeps track of the desired delay in ms as determined by the user, and it calculates
the number of addresses to be subtracted in the haas engine block, a
ddress
. address
is a
product of constant S
AMPLE_PER_MS
(set to 44 in our case for 44.1KHz sampling rate) and
integer delay_ms
. The controller takes inputs from up and down buttons, and it outputs
address
to h
aas_engine
as well as numeric information to the display.
Display: Mux 7 Seg
The controller outputs two 4bit signals, t
ens
and o
nes
, to the M
UX 7 segment display, which
in turn communicates which digits and segments on the Basys 3’s display to activate based on
8
the user selected delay amount d
elay_ms
. Because the maximum delay is 20ms, the hundreds
and thousands places are assigned to “0000.”
Minor Processes
The following minor processes were implemented in the top level:
Monopulsers: b
utton_up
and b
utton_down
inputs are monopulsed, or returned to
low only one clock cycle after being asserted, before being sent to the buttons
controller.
Clock Dividers: The serial_clock
signal is divided down 2.38MHz out of mclk
from Basys 3, and in turn the t
ake_sample_sig
signal is divided to 44.1Khz out of
(and monopulsed).
serial_clock
2.4. Construction and Debugging
When it came time to construct a hardware version of this effect, we knew a few key things
needed to be present: a ADC/DAC for getting audio into and out of the effect, a display to show
the delay amount, and buttons to increase or decrease the delay amount. The meat and bones of
the project is of course, the haas engine itself, which we ultimately decided to model after a large
shift register. In deciding how to instantiate the RAM, we chose to create a large enough array
and let Vivado decide how to best construct RAM as opposed to manually selecting a RAM from
the IP catalog.
Testbenching the controller and haas delay was easy and straightforward. The biggest
challenge of the project was simulating and debugging the ADC/DAC portion of the circuit. It
was difficult just to get the right stream of bits being sent to the ADC/DAC, and timing issues
9
made up for about half the debugging time. In addition to the tricky timing issues, we also had to
handle a DC offset issue. The chips only wanted to see audio above 0 volts, however audio
comes in a form that is centered around 0 volts. To solve this issue, we used a subtraction
technique that balances audio. By subtracting the inverted from the original signal, we were able
to manipulate the result to be above 0 volts coming out of the ADC, and then convert it back in
the DACs after the delay process. Additionally, even after we got the conversion process going,
we were still faced with massive noise and distortion. To solve this problem, we connected the
positive and negative pins to VCC and ground respectively with 1k resistors, which almost
completely took away the distortion problem. After that, implementing the haas engine was very
straightforward. We tied in all the code in the port maps and debugged minimal errors. It
performed perfectly, a welcome relief after the long (and painful) debug process of the
ADC/DAC.
3. Evaluation
In general, our implementation of the haas delay is clean and simple. We think our design for the
shifting register was a simple elegant solution to the problem of instantiating ram. Our initial
plan was to manually instantiate a dual ported RAM to handle the delay module, but we quickly
realized that would have b een more complicated than a simple (albeit large) shift register. If we
had to do this again with unlimited resources, we would change the way we handled the
analogdigitalanalog conversion by using different chips that didn't require the workarounds we
had to implement, such as tying resistors around the legs of the pins on the AD1.
10
4. Conclusions
At the end of this project, we’ve accomplished our goal of creating a working haas delay
effect module complete with display and user input buttons. Our f inal device is identical in
behavior to our proposed device despite various minor design adjustments.
Although we came out strong with a well drafted implementation of our design, we made
the unfortunate mistake of bypassing bottom up simulation in an attempt to patch everything
together first try. This was a lesson learned week after week in lab, yet in our endofterm
excitement, ignored one final time. In the end, we had to start a clean Vivado project, building
and testing each component ground up as we should have done all along. What could have been
a casual week or two of design and testing turned into a grueling pair of nine hour work nights.
For groups potentially interested in recreating our project, we would strongly suggest creating a
functional AD to DA path before pursuing any other implementation.
5. Acknowledgements
We would like to thank Professor Hansen, Dave Picard, and Liam Feeney for their time
consulting and aiding in the execution of our project. We would also like to thank William
Hogan for helping us improve the sound quality through our device and for treating us to lab
refreshments during our final debugging session.
11
PJ would like to thank his parents Cheryl and Joseph O’Sullivan for showing him enough
attention as a child, allowing him to flourish in his young adulthood without the burden of
unconscious insecurity.
Chris would like to thank his sponsors, Pioneer DJ and Orgain. Drink Orgain; c lean, great tasting
and convenient protein and nutrition made with the highest quality ingredients.
6. References
We heavily implemented ADC code from Chris Hogan and Max Wieland’s ENGS 31 Lab 5.
Further, we directly used the code for the MUX 7 segment display as written by Professor
Hansen and included in several previous labs. Other references were limited to previous labs and
lectures from ENGS 31.
12
7. Appendices
Appendix A: Front Panel
Appendix B: Block Diagrams
Appendix C: State Diagrams
Appendix D: Simulation Waveforms
Appendix E: Parts List
Parts List:
Artcessories
User's Manual
Signal Flow Chart
SPECIFICATIONS:
Frequency Response: 10Hz-50kHz +/-.5dB@
+4dBu
THD: .01% Typical @ 1kHz,
+18dBu, <.05% @ 100Hz,
+24dBu
Insertion Loss: .4dB@100k Ohm load,
5.5dB @ 600 Ohm load
Input Connections: XLR female balanced,
1/4-inch TRS balanced /
unbalanced, and RCA jacks
Output Connection: XLR male balanced, 1/4-inch
TRS balanced / unbalanced
and RCA jacks
Power requirement: Passive
Dimensions HxWxD(in): 1.75 x 4.2 x 3.5
HxWxD(mm) : 44.5 x 107 x 89