| ECE291 | Computer Engineering II | Lockwood, Spring 1999 |
Team Members:
Joshua Berry: Program flow, FFT
David Marshall: Sound, FFT
Joanna Washburn: Command handling
Tim Wilson: Graphics
Introduction
The Tunafish Music Tuner is a piece of software that
allows the user to tune an instrument. The Music
Tuner has a tone that matches the pitch of each of the twelve notes
in an octave. When the software is in
play back mode and one of the buttons is pressed, the tuner plays a
pitch in short segments until the button is
pressed again, or another button is pressed. The frequency of
the pitch is shown on the display, with a bar at
the fundamental frequency, or the frequency with the greatest intensity.
When in read in mode, the user can
play an instrument, and the frequency of the sound will be displayed
on the screen. If a button is first
pressed, a bar displaying the fundamental frequency of that pitch is
displayed. Also, a bar showing the
fundamental pitch of the sound played is displayed, and based on the
positions of these bars, the user can
adjust the pitch of the note played to match the target frequency of
the note that was pressed.
Problem Description
In order for our music tuner to work, we must be able to read in sound
from an instrument, and perform a
fourier transform on that sound. The code for the transform is
all original, written by our group, which makes
this project unique. Once the transform has been computed, we
can categorize each frequency range in a
defined number of bins, and then display each bin on the screen, in
histogram form, in essence displaying the
wave of that sound. This software will be mouse based, which
will require a mouse handler which will be
called either every time the mouse moves on the screen. This
will be accomplished by using an interrupt, and
setting the interrupt pointer of the mouse to our new procedure.
Next, we must manipulate the DMA to be
able to read in sound. This will require altering and adding
functionality to the sound library provided for us,
and setting up two separate pages in the DMA. The separate pages
will allow us to record sounds of
variable length without the restriction of the page size. We
can accomplish this by writing to one page of the
DMA while outputting from the other page. The ability of our software
to read in and analyze sound is
another unique aspect of our project. Once the sound is read
in, it will need to be stored in a wav file, to be
analyzed. Next, we will perform an fft on the input data, to
obtain a range of frequencies, with their
respective intensities, which will be stored in an array of bins.
A somewhat dynamic GUI will be needed,
and for this we will read in a tiled pcx file, and display the graphics
for the buttons and borders of the
interface by accessing the current tile to be displayed. An array
of pointers to tiles will indicate which tile
should be printed to what location on the screen, and will be constantly
updated, based on the actions of the
mouse. Over this skin, the display will be drawn, which will
be a histogram, using the data from the bins in
the fft structure. The display will have several features, depending
upon the mode we are in. For instance,
for tuning, a button will be selected indicating the note to be tuned
to. The display will then draw a bar at the
desired frequency, as well as one at the principle frequency of the
sound that was played from the
instrument. Also, the wave form of the sound played will be displayed.
The code for the display has the
ability to zoom in on the data, displaying either 256, 128, 64, 32,
16, or 8 frequency bins, depending on a
variable passed to the procedure. Then, we will draw the mouse
on top of the graphics. This will be
accomplished by double buffering. The skin will be read into
a 64k buffer, and then the graphics will be
written over the background of the display, and finally, the mouse
will be drawn over everything. Then, the
entire buffer will be dumped onto the screen. This eliminates
flicker on the screen. The most difficult
portions of this project will be designing an efficient fft algorithm,
and reading in sound of variable lengths and
magnitudes from the instrument. The graphics will require several
special cases, for the zooming capabilities,
and also for the skin. The buttons will show that they are pressed,
and need to be depressed once either
they are pressed again, or another button is pressed. Also, the
display will respond differently depending on
what mode the software is in. Once this project is completed,
it will provide a very useful music tuner.
Constants
| STOP equ 0 |
| PLAY equ 1 |
| RECORD equ 2 |
| QUIT equ 3 |
| _SB_HSvReg_Rec
equ 1
; record at 1 = HS, 0 = reg |
Structures
Struct PCXfile
| MANUFACTURER | DB 10 ; A ZSoft PCX File |
| VERSION | DB ? |
| ENCODING | DB 1 |
| BITS_PER_PIXEL | DB ? ; 1,2,4,8,24 (8 for ECE291 images) |
| XMIN | DW ? |
| YMIN | DW ? |
| XMAX | DW ? ; Window |
| YMAX | DW ? |
| HORZ_DPI | DW ? ; Horizontal Dots per inch |
| VERT_DPI | DW ? ; Vertical Dots per inch |
| PALETTE | DB 48 DUP (?) ; =< 16 colors |
| RESERVED | DB ? |
| COLOR_PLANES | DB ? |
| BYTES_PER_LINE | DW ? |
| PALETTE_TYPE | DW ? |
| HSCR_SIZE | DW ? ; only supported by |
| VSCR_SIZE | DW ? ; PBrush IV or higher |
| FILLER | DB 54 DUP (?) |
| IMAGE_DATA | DB FileSize DB ? ; RLE-Encoded Data ; (line-by-line) |
| PALETTE_MARK | DB 12 ; Indicates Trailer Palette |
| PALETTE_256C | DB 256 DUP('RGB') ; 768 Bytes of ; Palette Data |
Struct FFT
| FFTSEG | DW SEG SEGMENT SAMPLEBUFFER ; pointer ; to current part of Samplebuffer to ; analyze |
| FFTOFF | DW OFFSET OFFSET SAMPLEBUFFER |
| ENDOFBUFFER | DW 0 ; used to determine if not ; enough data in buffer to performFFT |
| BINCOUNT | DW 128 ; Variable containing the ; number of bins in the range to be ; displayed on the screen |
| BIN | DB 128 DUP (0) ; frequency bin array ; with magnitude value |
| GRAPHICS | DB 256X128 DUP (255) ; visual data to ; put to screen use the bin[] data to ; calculate this |
| FUNFREQ | DW ? ; Fundamental Freq identified |
| FUNBIN | DB 35 |
| TARGETFREQ | DW 440 ; Target Fundamental Freq |
| TARGETBIN | DB 43 |
Struct mousePos
| X | DW 0 ; X-pos 0 to 319 |
| Y | DW 0 ; Y-pos 0 to 199 |
| LB | DB 1 ; Left button status 0 if down, ; 1 if up. |
Struct SampleType
| INSTR | DB 0 ; index to table that contains ; Instr names |
| NOTE | DB 0 ; Pitch to play: 0=A, 1=A#/Bb, ; 2=B, ... 11=Ab/G# |
| REQUEST | DB STOP ; user request, either PLAY ; or STOP |
| STATUS | DB STOP ; actual status of player, ; PLAY or STOP |
Struct WaveHdr
| FORMAT | DB 'RIFF' ; Windows wav PCM format |
| FILELEN | DD ? ; Filelength |
| WAVEFMT | DB 'WAVEfmt_' |
| FMT_LEN | DD ? |
| FMT_TAG | DW ? |
| CHANNEL | DW ? |
| SAMPLES | DD ? ; Number of samples |
| BYTESPS | DD ? |
| BKALIGN | DW ? |
| BITSPS | DW ? |
| DATA | DB 'data' |
| DATALEN | DD ? |
Struct SkinTile
| tile | db 16*10 = 160 bytes per tile |
Struct COMP_STUCT
| R | REAL8 ? |
| I | REAL8 ? |
Variables
| tempbufferdb 64000 dup (?) | A buffer large enough to hold the compress data from a PCX file, including the header and trailer. Will use an entire segment |
| tempbuffer2 db 64000 dup (?) | Same as tempbuffer |
| SkinArray db 200 dup (160) | Array that is about 200 elements long, each element is 160 bytes long. This holds all of the tiles that will be printed to the screen. |
| TileIndex db 200 dup (?) | Array 200 bytes long, containing pointers to SkinArray |
| screenBuffer db 6400 dup (?) | Double buffer for mode 13h screen |
| SampleBuffer db 16384 dup (0) | Sound sample buffer. Will get broken into 2 pieces on the same page for smooth DMA transfers to and from SoundBlaster |
| SkinTile | 16X10 bytes of pixel data |
| MouseCursor db 400 dup (?) | 10X10 array of pixels. Use palette 255 to denote invisible color also, make icon point to the upper left corner |
| Mode db PLAY | Mode will indicate PLAY mode, record mode, or QUIT initialize to PLAY mode |
| NewCommand db 0 | 0 if nothing other than mouse or datascreen to update 1 if button pressed, wave file finished, etc. |
| sbuf_page db ? | Used for sound |
| sbuf_offset dw ? | Used for sound |
| sbuf_length dw 8192 | 8 k - all that is guaranteed to not cross a page |
| finalbuffersize dw ? | Used for sound |
| mycounter dw -1 | Originally –1, for switching between buffer |
| needrefill dw 0 | Used for sound |
| wavfile db
'AAA.wav',0 ; 0
db 'Asp.wav',0 ;1 db 'BBB.wav',0 ; 2 db 'CCC.wav',0 ; 3 db 'Csp.wav',0 ; 4 db 'DDD.wav',0 ; 5 db 'Dsp.wav',0 ; 6 db 'EEE.wav',0 ; 7 db 'FFF.wav',0 ; 8 db 'Fsp.wav',0 ; 9 db 'GGG.wav',0 ; 10 db 'Gsp.wav',0 ; 11 db 'vic.wav',0 ; 12 |
null terminated
file names, 8 bytes/file
0 - 15 is 1st (default) instrument = 128 bytes other instruments can be added as 15 - 31, etc. |
| fileno dw ? | file handle |
| wavremaining dd 0 | Used for sound |
| wavlength dd 0 | Used for sound |
| wavdone db 0 | Used for sound |
| loadbuf WaveHdr_STRUCT < > | Buffer withWavefile WaveHdr |
| RecordDone db 0 | Flag to indicate when enough recorded samples have been accrued |
| pitch SampleType < > | Pitch is a Sampletype structure |
| fft FFT_STRUCT < > | |
| Xvar COMP_STRUCT < > | Complex FFT variables |
| Yvar COMP_STRUCT < > | Complex FFT variables |
| Res COMP_STRUCT < > | Complex FFT variables |
| Iteration db 1 | FFT variables |
| Var1024 Real8 1024.0 | FFT variables/constants |
| Var256 Real8 256.0 | FFT variables/constants |
| Var128 Real8 128.0 | FFT variables/constants |
| Var2 Real8 2.0 | FFT variables/constants |
| Var0 Real8 0.0 | FFT variables/constants |
| ScaleIN Real8 2.0 | FFT variables/constants |
| ScaleOUT Real8 4.0 | FFT variables/constants |
| Buffer2Disk seg fft, offset fft.bin, 128 | FFT variables |
| ITempx qword ? | FFT variables |
| RTempx Real8 ? | FFT variables |
| ResultVar qword ? | FFT variables |
| mousePos mousePos_STRUCT< > | |
| BugFix db ? | For some reason this location in memory gets written into. So, this byte makes sure nothing important is written over. |
Macros
| ReadFile name(zero terminating string), es:di bufferaddr, numbytes, | set carry flag if an error occurred |
| UpdateScrn | bulk copy of the 64000 byte screenBuff to mode 13h scrn |
| ChangeButton | Author: Joanna
Washburn
Input:cx is how many to write (2 or 4) bx is which tile to start writing Output: changes tile index to new tiles |
| FindLeftCorner | Author: Joanna
Washburn
Input: Takes Tile Number from AccessTileIndex Output: finds top left corner of 4 tile button in bx |
| AccessTileIndex | Author: Joanna Washburn
Input: mouse position Output: where on screen you are in bx what tile is there in ax |
| ModeVideo13 | set Model13h VGA graphics |
| ModeTest | Set VGA for 80x25 text mode |
| movQW dst, sr | Josh's -- description: performs a
Quad word memory to memory copy that is optimized
fof speed. Uses eax and ecx for imtermediate steps |
| ClearQW add | Josh's -- description: resets a QWORD at location addr to zero. Uses eax for intermediate steps |
| DosExit | exit to dos |
External Procedures
SoundLib functions
Code: Micheal Urman
SB_Init:near
SB_Clean:near
SB_Play:near
SB_Stop:near
SB_SetCallback:near
SB_SingleCycle:near
Procedures
MouseInstall
Author: Joanna Washburn
Input: None
Output: None
Purpose: MouseInstall instructs the mouse driver
to call the Mousehandler routine for specified clicks.
Three calls to Int 33h routines
must be made in order to: reset the mouse driver, show the mouse cursor,
and set
MouseHandler to be the user
event handler for left-mouse-button (LMB) clicks.
MouseUninstall
Author: Joanna Washburn
Input: None
Output: None
Purpose: MouseUninstall will restore the mouse driver
to it's original state by first hiding the mouse cursor, then resetting
the driver.
MouseHandler
Author: Joanna Washburn
Input: AX = event mask (same format as described
in MouseInstall above)
BX = mouse button status
Bit 0: LMB activated
Bit 1: RMB activated
Bit 2: MMB activated
CX = horizontal mouse position
DX = vertical mouse position
DS = data segment of the mouse driver
Output: MousePos.X = horizontal position of mouse
MousePos.Y = vertical position of mouse
MousePos.LB = status of the left button (pressed or released)
NewCommand = whether or not left mouse button is pressed.
Description: MouseHandler will be called by the
mouse driver. It updates the MousePos structure which includes the horizontal
position (X), the vertical
postion (Y), and the status of the left mouse button (LB). NewCommand
also gets updated.
PerformCommand
Author: Joanna Washburn
Input: NewCommand = variable indicating whether
or not the left mouse button is pressed
MousePos structure
Mode = variable giving status of software (Play, Record, or Quit)
Output: Sample.inst = the instrument
chosen
Sample.note = the pitch to be played
Fft.lowFreq = low frequency to center around desired pitch
Fft.hiFreq = high frequency to center around desired pitch
Mode = updated
tileIndex = updated
Description: PerformCommand will take inputs
from the mouse handler and determine the mode, pitch, instrument, etc.
that was
selected by determining
which tile was chosen.
DecompressPCX
Author: Tim Wilson
Input: PCX file containing all of the default tiles
that will be used in the GUI skin
Output: The PCX file is stored in a temporary variable
called tempbuffer
Purpose: DecompressPCX uses several interrupt calls
to open a specified PCX file and read the data into tempbuffer so that
the file
can be later stored as an
array of tiles.
SetPalette
Author: Tim Wilson
Input: tempbuffer = buffer of length 64000 which
holds the data from the pcx file
Output: Adjusts the palette settings to correspond
to the ones used in the PCX file
Purpose: SetPalette reads the palette information
from either the header or trailer of the PCX file and sets the computer’s
palette
to match.
FillSkinArray
Auhtor: Tim Wilson
Input: tempbuffer
Output: SkinArray = an array containing the image
data from the PCX file
Purpose: FillSkinArray takes the image data from
the PCX file and stores it in tiles; these tiles make up the array called
SkinArray.
Each tile is 160 bytes,
or 16x10 pixels in dimension. The array has its own segment, and uses it
all.
GenerateCurSkin
Author: Tim Wilson
Input: SkinArray = an array containing the
image data from the PCX file
tileIndex = an array containing pointers to tiles in SkinArray
Output: Writes to the screen the current image of
the GUI
Purpose: GenerateCurSkin writes to the screen 200
tiles from SkinArray to the screen, as specified by tileIndex. TileIndex
is an array
200 bytes long, which specifies
which tiles from SkinArray will be printed to which portions of the screen.
TileIndex is updated
each time the mouse interrupt
updates detail and this function constantly redraws the screen based upon
this base skinarray.
GenerateFFTGFX
Author: Tim Wilson
Input: fft structure
Output: Writes to the screen a graphic representation
of the input sound wave
Purpose: GenerateFFTGFX reads information from the
fft structure, such as lowFreq, hiFreq, binCount, bin, and graphics, and
creates
a set of bars to indicate
the strength of the signal at a given frequency. The greater the strength,
the taller the bar at that frequency
bin, and thus a set of bars,
similar to a graphics equalizer, except with many more bars, will be displayed
on the screen.
LoadMouse
Autor: Tim Wilson
Found in graphics.inc file
Input: Mouse.pcx = pcx file containing mouse cursor
Output: MouseCursor = array containing decompressed image
of mouse cursor
Purpose:
LoadMouse opens Mouse.pcx and stores
the image data in the array
MouseCursor.
OpenWav
Author: David Marshall
Derived from : Mike Urman's code
Found in play.inc file
Purpose:
Open a .wav file and advances to the beginning of
the data
Input:
Pitch SampleType < >
SampleType_STRUCT STRUC
INSTRU DB 0 ; index to table that
contains Instr names
NOTE DB 0 ; Pitch
to play: 0=A, 1=A#/Bb, 2=B, ... 11=Ab/G#
REQUEST DB STOP ; user request, either
PLAY or STOP
STATUS DB STOP ; actual status
of player, PLAY or STOP
SampleType_STRUCT ENDS
Output:
wavlength : gets size of total .wav
wavremaining : gets size of total .wav because that
is how much is left
Description:
Use INT 21h, Open File (3Dh) and Read File (3Fh)
MainPlayWav
Author: David Marshall
Derived from : Mike Urman's code
Found in play.inc file
Purpose:
The control function that orchestrates the playing
of a specified .wav file
Input:
Pitch SampleType<>
SampleType_STRUCT STRUC
INSTRU DB 0 ; index to table
that contains Instr names
NOTE DB 0 ;
Pitch to play: 0=A, 1=A#/Bb, 2=B, ... 11=Ab/G#
REQUEST DB STOP ; user request,
either PLAY or STOP
STATUS DB STOP ; actual
status of player, PLAY or STOP
SampleType_STRUCT ENDS
Output:
Sound of .wav
Sample.status updated
Description:
1. Calculates linear address of buffer
2. Set sbuf_length to 8192
3. Determines 2 4K buffer that lie on same page
4. initialize soundcard and install ISR
5. Set up SoundHandler a fn of ISR
6. Open .wav
7. Play the .wav with all of the single cycle complexities
LoadHalfBuffer
Author: David Marshall
Derived from : Mike Urman's code
Found in play.inc file
Purpose:
Takes a 1 or 0 in ax, and reads from the file into
the
appropriate half of sndbuf.
Input:
AX = identifies which half of sndbuf to write to
sbuf_page = db
?
sbuf_offset = dw
?
sbuf_length = dw
8192
Output:
finalbuffersize = how much data is in this final
buffer
wavdone = inc to 1 if done,
inc to 2 on end case = interupt is called and says it needs
refill so LoadHalfBuffer is called and loads nothing
while other half buffer is being played
wavremaining = wavremaining - bytes read in this
load
Description:
each page is 64k
our sndbuf is 16k
we define our sbuf_length to be 8k
we only write to 1/2 buffers or 4k pieces
SoundHandler
Author: David Marshall
Derived from : Mike Urman's code
Found in play.inc file
Purpose:
SoundHandler is called whenever the DSP generates
an interrupt
Input:
None
Output:
mycounter = increments it
needrefill = increments it to 1 everytime
Description:
Installed by SB_SetCallback in library; called in
MainPlayWav.
MainRecordWav
Author: David Marshall
Derived from : Mike Urman's code
Found in record.inc file
Purpose: Record a 1K sample
Input:
None
Output:
1024 samples in the sndbuf and the location
of it via
FFT_STRUCT STRUC
FFTSEG
DW ?
FFTOFF
DW ?
...
FFT_STRUCT ENDS
Description:
1. Calculates linear address of buffer
2. Set sbuf_length to 1024
3. Determines 1 1K buffer of our 16K buffer that
lies on one page
4. Tell fft variable where buffer is
5. initialize soundcard, turn off speakers, and
install ISR
6. Selects RecordSoundHandler far procedure to call
from
the SoundBlaster interrupt.
7. Calls SB_Record
RecordSoundHandler
Author: David Marshall
Derived from : Mike Urman's code
Found in record.inc file
Purpose:
SoundHandler is called whenever the DSP generates
an interrupt
Input:
None
Output:
RecordDone = increments it to one when done
Description:
Installed by SB_SetCallback in library; called in
MainPlayWav
WriteRecording
Author: David Marshall
Found in record.inc file
Purpose: Mostly debugging uses, but it also would allow
us to store our
recorded sound for later uses
SB_Record
Author: David Marshall
Derived from : Mike Urman's code
Found in Sblib291.asm file
Description:
Set up DMA (channel 0) to transfer to the memroy
from SB
Program the DSP for 8-bit cycle DMA mode transfer
Programs DMA and DSP to record to specified buffer.
Input :
ax = offset of the sound buffer (relatve to page)
bh = 0 for regular 8-bit Mono Single-cycle Transfer
= 1 for 8-bit Mono High Speed
Single-cycle Transfer).
bl = page of the sound buffer
cx = length of the sound buffer
Output:
a 1024 buffer of data in from mic
_ProgramDMA_Record
Author: David Marshall
Derived from : Mike Urman's code
Found in Sblib291.asm file
Description:
Set up DMA (channel 0) to transfer to the memroy
from SB
Input:
ax = page offset of the sound buffer
bl = page # of the sound buffer
cx = length of the sound buffer
Output:
none
_ProgramDSP_Record
Author: David Marshall
Derived from : Mike Urman's code
Found in Sblib291.asm file
Description:
Set up SB DSP to record an 8-bit Mono Single-cycle
transfer
1. Set the DSP transfer Time Constant
For reg
2. Send an I/O command folowed
by data transfer count
For HS
2. Set the DSP block size
3. Send an I/O command to
start HS SC DMA mode transfer.
Input:
cx = length of the sound (transfer count value
will be one byte less than
actual length of sound)
bh = 0 for regular 8-bit Mono Single-cycle
Transfer
= 1 for 8-bit
Mono High Speed Single-cycle Transfer
(maybe we need high speed for real time action)
Output:
none
_TurnOffSpeakers
Author: David Marshall
Found in Sblib291.asm file
Description:
Turns off speakers
Input: none
Output: none
SB_Init_Record
Author: David Marshall
Derived from : Mike Urman's code
Found in Sblib291.asm file
Description:
Attempts Initialization the sound card and reports
on success/failure
Input: none
Output:
carry flag: set on installation failure
SB_BaseAddr, SB_IRQ, SB_DMA_Low set appropriately
ISR installed
ComplexMul
Author: Joshua Berry
Found in fft.inc file
Purpose:
Peform necessary multiplication using complex
numbers on FP stack.
Complex multiplication = 4 real multiplications,
1 real add, and 1 read sub.
Input:
Xvar COMP_STRUCT < >
Yvar COMP_STRUCT < >
Ouput:
Res COMP_STRUCT < >
PerformFFT
Author: David Marshall and Joshua Berry
Found in fft.inc file
Purpose:
Implement the FFT algorithm (decimation in
frequency) (Fast DFT)
Input:
1st half of tempBuffer (serves as 2 buffer
dividing tempBuffer in 2)
Samples are in a+jb fashion, where a and b
are Real 8
Output:
1st quarter of tempBuffer. 1024 results
in bit reversal order.
Results are of same complex convention
ConvIntFL
Author: David Marshall and Joshua Berry
Found in fft.inc file
Purpose:
Convert an integer to REAL 8 format.
Then subtract 128 and divide by 128.
Then result is complex Real8 samples valued
between 1 and -1, which is
the required format for the Perform FFT function.
Input:
fft = var of type
FFT_STRUCT STRUC
FFTSEG
DW ?
FFTOFF
DW ?
....
FFT_STRUCT ENDS
Output:
tempBuffer <-- 0...16k (1024 of FFT_STRUCT)
FinalizeResult
Author: David Marshall and Joshua Berry
Found in fft.inc file
Description:
Get the 1st 128 bins (the lower frequencies)
by
feeding index we want through bit reversal,
indexing memory with it
to get the value (a Complex number).
Calculate the Magnitude (Real8 between 0 and
1) (Net whole signal = 1).
Scale by 256. (so value fits in a byte).
Then store in corresponding bin.
Input:
1st half of tempBuffer
Output:
fft = a var of type
FFT_STRUCT STRUC
....
BINCOUNT
DW 128
BIN
DB 128 DUP (0)
....
FFT_STRUCT ENDS
BitReverseMap
Author: David Marshall
Found in fft.inc file
Purpose:
To Return the bit reversal of an index so
we can retrieve the value
of the original index from memory; assuming
0 to 1023 <-- important
Input:
ax: the index you want
Output:
bx: the bit reversal value (10 bits only)
of that value
Description:
Bit 9 <-> Bit 0
Bit 8 <-> Bit 1
Bit 7 <-> Bit 2
Bit 6 <-> Bit 3
Bit 5 <-> Bit 4
FindFunFreq
Author: Joanna Washburn and David Marshall
Found in fft.inc file
Pupose:
Find the lowest bin with the highest
magintude
Then convert to freq <-- Didn't use
in final
Input:
none
Output:
none
MAIN ....
Main PROC far
mov
ax, cseg
mov
ds, ax
ModeVideo13
Call MouseInstall
mov
dx,offset mouse
Call LoadMouse
mov
dx,offset tunerSkin ; Load tunerSkin into
pcx variable, transfer
Call DecompressPCX
; image data to tempbuffer, set palette
Call FillSkinArray
; convert tempbuffer to tiles in SkinArray
Call GenerateFFTGFX
Call GenerateCurSkin
UpdateScrn
;play intro wav
mov
pitch.note, 12
mov
pitch.request, PLAY
CALL MainPlayWav
mov
pitch.request, STOP
;set the bins to 0
mov
cx, 128
xor
bx, bx
BinsTo0:
mov
fft.bin[bx], 0
inc
bx
Loop BinsTo0;
MainLoop:
cmp
Mode, QUIT
je
ExitTuner
cmp
Mode, REC
je
RecordLoop
PlayLoop:
CALL PerformCommand
;if command present, perform it
; Push ax
; mov ax, offset pitch
; Pop ax
CALL MainPlayWav
CALL SwitchWave
CALL GenerateCurSkin
CALL GenerateFFTGFX
UpdateScrn
CALL GenerateCurSkin
CALL GenerateFFTGFX
UpdateScrn
;macro, copy dub-buff to scrn
jmp
MainLoop
RecordLoop:
CALL PerformCommand
;if command present, perform it
CALL GenerateCurSkin
CALL GenerateFFTGFX
UpdateScrn
;macro, copy dub-buff to scrn
CALL MainRecordWav
mov
fft.FFTSEG, seg sndbuf
mov
fft.FFTOFF, offset sndbuf
CALL ConvIntFL
CALL PerformFFT
CALL FinalizeResult
CALL FindFunFreq
CALL GenerateCurSkin
CALL GenerateFFTGFX
UpdateScrn
mov
cx, 5
GIVEITTIME:
CALL GenerateCurSkin
CALL GenerateFFTGFX
UpdateScrn
;macro, copy dub-buff to scrn
LOOP GIVEITTIME
jmp
MainLoop
ExitTuner:
CALL MouseUninstall
ModeText
;macro to switch to textmode
Exit2Dos
;macro that makes int 21 exit to dos call
main endp
cseg ends
end main