some ZX Spectrum related Z80 assembly routines about the AY sound chip




HELLO , WORK IN PROGRESS
very rumbly indeed
many software is aimed on standard herz like 8 khz, 11 khz, but since ZX is rather slow and downrating I prefer to aim to make a WAVE file that fits to the ZX speed instead off the 'obvious' standard. The different assembly routines I recently wrote all have different maximum speeds. My routine had a 'tic' or 'click' sound. I changed my 'init' procedure for the AY chip since I discovered that register 7, the mixer reg, is set to 255 on a fresh ZX which the routine does set now thus ending with a true silence setting

Z80 ASM SoX WAV2AY PCMENC
AYpD_0007.asm
just the IDEA to play direct from disc.
'raw 2 ay'
ZX Speccy can do it
nwAY1ch065.zip
A+B+C used as 1 channel
zxv4P4_042c.7z
Press '0' to load '54321.bin' zxVplayer+zxv4P4_042c+54321bin.tap
r2ayR8_036.asm
a very simple 8 bits RLE
3chsmpl078b.asm
a 3 channel player,plays 3 different sounds at once,
lowest key row is used for input
sox_raw.bat
3chsmpl078b+bas.z80
3Csmpl103+bas.tap
pcmenc_zx003.bat

Its all started with the crossover cq external software WAV2AY for ZX Spectrum combined with the AY-3-8910 sound chip.
Then I found PCMENC and SoX which are great programs aswell to reach the "4 bit wave magic" on ZX Spectrum.
Both PCMENC and WAV2AY make use off SoX as convertion application. I think I found the 'perfect' SoX commandline to split waves in parts of severall seconds or sample-blocks
Sox has a default setting to use 'dither' in the samples, but since we downrate a lot , the added noise will hinder a clear sound. The command '-D' switches dither OFF. You can check differences in sound by removing and adding the '-D', maybe you like dithering after all.
The 'trim' command uses 'time in seconds' or samples to count with, and the 's' indicates SAMPLES. SoX tends to measure the cutting on the original wave and STARTS with trimming before any conversion. Since 'down rating' in convertion is equal to cutting out data samples in a sequence, this COULD mean a sample inbetween is lost and the connection between wave-blocks gets 'out off sync' with odd rest numbers
So its probably better to first convert to RAW, but then sox is unhappy without a specified 'sampling rate', I am looking for a workable solution.

sox -V3 -D filename.wav -r 9560 -b 8 -e unsigned -c1 othername%1n.raw trim 0s 10240s : newfile : restart

Input File : 'mozarts15a.wav'
Channels : 2
Sample Rate : 44100
Precision : 16-bit
Duration : 00:00:54.98 = 2424684 samples = 4123.61 CDDA sectors
File Size : 9.70M
Bit Rate : 1.41M
Sample Encoding: 16-bit Signed Integer PCM
Endian Type : little
Reverse Nibbles: no
Reverse Bits : no
Level adjust : 1 (linear gain)

Output File : 'moznm19.raw'
Channels : 1
Sample Rate : 9560
Precision : 8-bit
Sample Encoding: 8-bit Unsigned Integer PCM
Reverse Nibbles: no
Reverse Bits : no
Comment : 'Processed by SoX'

sox INFO sox: effects chain: input 44100Hz 2 channels
sox INFO sox: effects chain: trim 44100Hz 2 channels
sox INFO sox: effects chain: channels 44100Hz 1 channels
sox INFO sox: effects chain: rate 9560Hz 1 channels
sox INFO sox: effects chain: output 9560Hz 1 channels
sox WARN trim: Last 1 position(s) not reached (audio shorter than expected).


mozarts15a.wav
I found above wave here here buts its obviously to large for any ZX so my aim with this piece off Mozart is to put it on an MGT disc, for +D or DISCiPLE and TRY to play it as a stream from disc.... but timings between FDC, ZX and AY will be difficult and until I start and try to code for real, its just a ridiculous idea AYpD_0007.asm
It would be nice if the expected Herz , in "-r 9560" , is changable aswell since the range of the new wav2ay is to be expected between 6kHz to 13 Khz wave forms. All in 4bits. SoX is able off converting loads off different formats anyway, so that gives possible future implementations already,
Luckely batchfiles are flexible AND you can start them with extra variables in the execution process

As said I use 3 main programs, working in Windows, that help convertion WAVE files to AY format. A difficult part is that there is not a real 'ay-standard' although a common AYfile has 2 samples in 1 byte, %1111 + %1111, just like the old *.VOC files used in telephone software. Yet the VOC samples are SIGNED 4 bit values and the AY are UNsigned 4 bit values.
the PCMencoder uses 4bit OR 3bit RLE compression and a 4bit sample in 1 byte
i made a ZX version for it, you can choose some settings for rl3 or rl4 and include a KEY and DELAY option, which slows down the final assembled machinecode, which calculates the desired DT1, DT2 and DT3 in its 'symboltable'

last developement for RL4 is now zxVplayer_4p4033.zip and I included the 'workfiles'. The actual wav data is 31701 bytes for 3.5 seconds, but the amount off SAMPLES is bigger!!!
With this example your FIRST have to press '0' to actualy LOAD the binfile on TAPE. then press ENTER zxv4P4_033+bas+54321.tap

zxv4P4_022+bas+plop.z80
zxv4P4_022.asm


I try to make a Z80 convertor for the RAW file made by SoX. its based on 'sam2ay.pl' which you will find in the 'wav2ay_src' link above.
until now thats 'raw 2 ay'
you can use 3 different 'curves' or make your own and poke it with the Basic routine.

This is an 8bits RLE r2ayR8_036.asm
This is an PlusD disc image to be used with ZX Spectrum 48k or 128k raw2ay+rle_003.mgt
meanwhile I started with adding RLE compressing thats used ON THE FLY while playing, so hopefully thats a good reduction off the file space needed.

the RAW file is an 8bit file which has to be reduced to a 4bit file. The AY 'raw' has 16 states 0 to 15. 0 will remain 0 so there are 15 positions between 1 and 255, afai understand. 256 steps have to become 16 steps. which CURVE is best ?
option 1) Gasman's curve is now used: total= 2+ 3+ 2+ 3+ 4+ 5+ 10+ 11+ 16+ 24+ 23+ 28+ 30+ 36+ 39+ 20 = 256 steps in 16 steps
Its a siniod but with INTed values of course, 4bit '0' = 8bit 0-1

option 2) is a simple calculation , a bit 'fractalistic'
n+(n+1) total=(0+1)+(1+2)+(2+3)+(3+4)+(4+5)+(5+6)+(6+7)+(7+8)+(8+9)+(9+10)+(10+11)+(11+12)+(12+13)+(13+14)+(14+15)+(15+16)=256 in 16 steps
n+(n+1) total= 1+ 3+ 5 + 7 + 9+ 11+ 13+ 15+ 17+ 19+ 21+ 23+ 25+ 27+ 29+ 31 =256 in 16 steps, 4bit '0' = 8bit 0 - 0 (!)

option 3) the simple linear methode is to divide by 16, which is equal to extract only the high 4 bits from an unsign 8bit sample. 4bit '0' = 8bit 0-15

severall variations

I make use off the online emulator called QAOP, thanks JB.
For further info about QAOP and eventualy bugs you can check his site.
if the sound is not working then move the mouse left and click on the "AY" button. it should have a DOT.
Jan updated the engine so I dont expect an "out of memory " for the ramdisc use, but if any might occur,
just move the mouse to the left, press RESET,
and click in the middle of the white emulator screen, then press enter
it should activate the "load tape" option of ZX

assembly file ends with 'asm':

rle-attempt_021_b.tzx


nwAYrle080+bas.tap


abc.tap


nwAY1chan046.z80
nwAY1chan046.asm


n_wAYv+wav0017+bs015.z80


nwAYrle078+bas.tap


nwAY3ch055.tap


plop-bump-flut.z80


some links:
https://en.wikipedia.org/wiki/ZX_Spectrum
https://en.wikipedia.org/wiki/General_Instrument_AY-3-8910
https://en.wikipedia.org/wiki/Dialogic_ADPCM
http://sox.sourceforge.net/AudioFormats-11.html