CSC231 Homework 6 Solution 2010
--D. Thiebaut 14:58, 12 November 2010 (UTC)
;;; hw7Sol.asm
;;; D. Thiebaut
;;; Solution Program for HW #7
;;; reads a wav file, and adds an echo to it.
;;; Algorithm:
;;; first clear the whole buffer, to make it silent
;;; read the sound file goodby2.wav, record N samples: abcdef...z
;;; make a copy of all N samples at the end of the first N samples: abcde...zabcde...z
;;; add shifted value of first N samples over second half, with an offset of 1500. Shift is 1 bit
;;; add shifted value of first N samples over second half, with an offset of 3000. Shift is 2 bits
;;; copy N+3000 samples from second part of buffer to first part of buffer
;;; write N+3000 samples to goodbye2.wav.
;;; The name of the wav file is hard-coded in the program: goodbye.wav
;;; The name of the output file is also hard-coded: goodbye2.wav
;;;
;;; This program uses wav.inc for accessing the wav file.
;;; wav.inc contains a 100KB buffer to hold the wav file
;;;
;;;
;;; Example of use:
;;; nasm -f elf hw7sol.asm
;;; ld -o hw7sol hw7sol.o
;;; rm goodbye2.wav
;;; aplay goodbye.wav
;;; ./hw7sol
;;; aplay goodbye2.wav
;;;
%include "wav.inc"
;; -----------------------------------------------------------
;; data segment
;; -----------------------------------------------------------
section .data
fileName db "goodbye.wav",0
fileName2 db "goodbye2.wav", 0
noBytesSamples dd 0 ; # of bytes of samples
bufferAddress dd 0 ; safe place to keep address of buffer
offset dd 1500 ; offset for echo
endBuffer dd 0 ; address of 1st empty byte after sound
; samples
noShifts db 1 ; amount of shifting to do with
; the echoed sound. Shifting by 1 means
; dividing by 2.
;; -----------------------------------------------------------
;; code area
;; -----------------------------------------------------------
section .text
global _start
_start:
;;; clear the whole buffer. This actually makes the whole
;;; buffer contain silent sounds...
mov ecx, MAXBUF + (buffer-wavbuf)
mov ebx, buffer
.for: mov byte [ebx], 0
loop .for
;;; open the file and put its contents in Buffer.
;;; keep track of # of bytes read in noRead
mov ebx, fileName
readSoundFile
mov [noBytesSamples], eax
mov [bufferAddress], ebx
;;; compute address of free space at end of buffer
mov eax, [bufferAddress] ; compute beginning address of
add eax, [noBytesSamples] ; space at end of sound
mov [endBuffer], eax ; save it
;;; make a copy of the original sound at the end of itself in buffer
;;; make esi point to buffer
;;; make edi point to end of buffer so that we can copy original file in
copy1: mov esi, [bufferAddress]
mov edi, [endBuffer]
mov ecx, [noBytesSamples]
.for: mov al, [esi]
mov [edi], al
inc esi
inc edi
loop .for
;;; add original sound over its copy, dividing intensity by 1/2
;;; and with an offset of 1500 (or whatever is in [offset])
call copyAdd
;;; add original sound over its copy, dividing intensity by 1/4
;;; and with an offset of 3000 (or whatever is in [offset])
mov eax, [offset]
add [offset], eax ; double offset size
inc byte [noShifts] ; get ready to divide by 4
call copyAdd
;;; copyBack to original buffer
copyBack:
mov esi, [endBuffer]
mov edi, [bufferAddress]
mov ecx, [noBytesSamples]
add ecx, [offset]
add ecx, [offset]
.for: mov al, [esi]
mov [edi], al
inc esi
inc edi
loop .for
;;; same code, but this time divide
;;; write contents of buffer to same new file
mov ebx, fileName2
mov ecx, [noBytesSamples]
add ecx, [offset]
add ecx, [offset]
writeSoundFile
;;; exit()
mov eax,SYS_EXIT
mov ebx,0
int 0x80 ; final system call
;;; -------------------------------------------------------------
;;; copySound: copy from esi to edi a number of bytes the number
;;; of which is in ecx. Registers unmodified.
;;; -------------------------------------------------------------
copySound:
pushad
.for: mov al,[esi]
mov [edi],al
inc esi
inc edi
loop .for
popad
ret
;;; -------------------------------------------------------------
;;; copyAdd: copies samples from beginning of buffer address
;;; to end of buffer + offset. Each original sample
;;; is first shifted by the amount in [noShifts] before
;;; addition. Sound is clipped to 255 if result of
;;; addition overflows.
;;; -------------------------------------------------------------
copyAdd:
mov esi,[bufferAddress]
mov edi,[endBuffer]
add edi,[offset] ; point 1 offset away in 2nd buffer
mov ecx,[noBytesSamples]
.for: mov al, [esi] ; get original byte
mov ah, 0 ; get ready to get shifted bit
push cx
mov cl, [noShifts]
shr al, cl ; decrease original sound according to what's
pop cx ; in cl
add al, [edi]
adc ah, 0 ; put the carry of the previous operation
; in ah
neg ah ; transform 0 in 00000000 or 1 in 11111111
or al, ah
mov [edi], al
inc esi
inc edi
loop .for
ret