Creating ZX SOUND

Started by Baggey, February 01, 2021, 08:17:48

Previous topic - Next topic

Midimaster

The little running man in the game (FUSE-video at 0:38) need 16sec to do his way 3 times.

In your 44.100 simulation (FUSE-video at 1:57) he needs 18sec to do the same. This would mean the TCycles/msec have to be 3937 and not 3500.

What do you think?
...on the way to Egypt

iWasAdam

#106
QuoteCode: BlitzMax
That's really helpful. it gives me an understanding of what is going on and how you are sending data/info to the 'blackbox' ringbuffer

Right - And I know someone is going to go nuts over this...
the speed of the ring buffer should have no effects on the sound output. E.G. The RingBuffer (I'm just going to call it RB from now on), will have a frequency that the audio driver is happy with. you send data to the RB and it outputs the result.

BUT... and it is a big one....

It may be that the internal operation of the RB is not operating in a way that the spectrum output would like.

Without testing the RB. My thought is the following:
you send the RB 50. it registers 50, outputs 50 and continues to output whatever 'other' value it likes. I would have thought that the RB would continue sending the value of 50, until it was told to send another different value.
So you send 50 first, then a 0 later and so on. this is what gives the square wave?
NOTE - sending 150 and 100 would actually give the same result as sending 50 and 0 - why - because it is the difference between the values that matters.
In the spectrums case- 0 is off and a louder volume is on
I did some checking and the beep command only has a freq and length. So the spectrum never really used volume - which is good to know

This would mean that for and z80 speed, the pitch comes directly from this speed. - It's also why a NTSC and PAL spoectrums have slightly different pitch frequencies - 60 htz vs 50 htz clock speeds.

You would need to test and check this though...?


Midimaster

Quote from: iWasAdam on August 01, 2021, 10:24:50
QuoteCode: BlitzMax
the speed of the ring buffer should have no effects on the sound output. E.G. The RingBuffer (I'm just going to call it RB from now on), will have a frequency that the audio driver is happy with. you send data to the RB and it outputs the result.

The FreeAudioRingBuffer has no "speed". It is a passiv element. Filled by the user's call RingBufferSendOne(), emptied by the FreeAudio-Driver
The FreeAudio-Driver has a "speed": the amount of data per msec is related to the Hertz we startet it.



Quote...It may be that the internal operation of the RB is not operating in a way that the spectrum output would like.
Without testing the RB. My thought is the following:
you send the RB 50. it registers 50, outputs 50 and continues to output whatever 'other' value it likes. I would have thought that the RB would continue sending the value of 50, until it was told to send another different value....

The current use of the ringbuffer is sending SILENCE (=0), when the buffer is empty. That fits to a lot of situation where you would use such a ringbuffer. It would also fit to a perfect adjusted Z80 if it sends exactly the amount of data the FreeAudio-Driver needs

But that is a good idea of you! We should try to send the LAST VALUE instead of silence. This would keep the speaker in the last state until a new OUT_254 comes in. This will prevent all timing problems, but of course will cause pitch fluctuations. Maybe it will sound ugly, maybe it will lead us exactly to the typical dirty sound of vintage computers.


QuoteThis would mean that for and z80 speed, the pitch comes directly from this speed. - It's also why a NTSC and PAL spoectrums have slightly different pitch frequencies - 60 htz vs 50 htz clock speeds.

That is correct! You got it! At Z80 Music pitch was related directly to the processor speed. That why it is so important to adjust also the HERTZ of the Freeaudio-Driver to the vintage situation. There was no 44100 in this times. The game pushes single BYTEs to the OUT_254 and the speaker reacts on this timing. We can simulate this with sending 0 and 255 to the ringbuffer, which gives a very loud signal.  Or we send 100 and 150, which produces a quiter signal. But the signal should dance around 0 Volt, which is 128 in SF_MONO8. Sending 0 and 50 to the ringbuffer leads to -32768 and -19968 sent to the FreeAudioDriver and this means a permanent DC at the speakers. A sound engeneer will tell  you that this is not the best way to handle speakers. In german we call this mid-point "Nulldurchgang" what means Zero-Level in english.

Often misunderstanding comes from the different nativ languages we speak.



...on the way to Egypt

iWasAdam

I do think that one thing should be thought about:
QuoteBut the signal should dance around 0 Volt

Not strictly true - it may actually sit at 0v-5v. I would have to look at the exact spectrum specs. but doing some research the spectrum used a 1bit speaker system. with frequency control giving limited pitch over 10 octaves.

My thought here would to do some primitive tests using video examples to compare the outputs of both.


The only other warning sign I get is to do with hrtz and speed and slowdown.
the sound system should be almost completely removed from the z80/spectrum core - just sending data as and when needed. each should do it's own thing in almost isolation from the other - there should be no real slowdown of speed. There would be differences in debug vs release versions as debug would have at least twice the overhead because if the inserted debug code.

In the above example of a single 1 bit channel emulation - you would have no audible difference in either debug or release as the speed changes would be almost none. You are only sending an on/off signal...

I usually have trouble with debug when using more that 3-4 16bit channels or realtime audio... and then only slowdowns. you should not be having any issues with speed in any situation - unless there is something 'odd' going on with the code.

BTW I run my ring buffer at 44100 - you should never need to do any housekeeping with this as it should 'just' work. Once set up you don't have to think about it, etc. There should no no messages about unfilled buffers, no intentional slowdowns, etc. The core buffer design is the most important part as everything is built on top of it.

Midimaster

We already did video comparation and I found out that Baggey would need 3937 cylcles/msec to run in the same speed like FUSE simulator. When we do this the little running man runs the same speed in both videos. (factor 1.12)

When comparing audio pitch it would be neccesary to run the FreeAudio-Device with 64.0kHz to reach the same tune. (factor 1.45). Running with 32.0kHz will feed the Device perfect, but the pitch is now too low. Filling a 64.0kHz Device with the given 3500 cyles/msec and auto-completing missing BYTE with doubling the last one will also cause in a real deeper pitch.

As the source code of my FreeAudioRingBuffer is Public Domain everybody is free to manipulate and adjust it to his needs. Also the fact that it has only 300 lines of BlitzMax code should help to easy change something.

I also already thought about offering an option to switch off the AUTO-DELAY (which prevents buffer overruns) in the next version.

Together with Baggey I developed a Z80-timing system that runs exactly with 3500 ticks/msec in every situation. It does not matter, whether we are in DEBUG or RELEASE mode or whether  other background processes need more time. Also the RingBuffer has no effect on the Z80-processor speed. This was a necessary first step to start investigations about finding out how we can/need do handle the audio timing.


Your access of always using 44.1kHz is perfect for a new app, because you are able to provide data in the needed speed. But Baggey situation is different. He has to handle with the given 3500 cycles. Sometimes during this game code there is a code line for the OUT_254 (speaker). This defines the speed of feeding the speaker. Now we have to find out, what is the best corresponding HERTZ  in FreeAudio-Driver related to this feeding.

You are welcome to offer code snipplets Baggey can add to his code.
...on the way to Egypt

iWasAdam

No probs - the only code issues I have is I don't use blitzNG - I moved to monkey2 and now have finished transition to Wonkey (now I've finished writing the editor)

There are significant differences with accessing c code (why I said don't attempt to run with prev code sample ;( ) with NG and Wonkey.

I was toying with moving back to NG - but found it was just too old to comfortably do what I needed. so whilst I can talk concepts and pseudo code, my code is firmly fixed with wonkey...

Baggey

Quote from: iWasAdam on August 01, 2021, 14:28:40
No probs - the only code issues I have is I don't use blitzNG - I moved to monkey2 and now have finished transition to Wonkey (now I've finished writing the editor)

There are significant differences with accessing c code (why I said don't attempt to run with prev code sample ;( ) with NG and Wonkey.

I was toying with moving back to NG - but found it was just too old to comfortably do what I needed. so whilst I can talk concepts and pseudo code, my code is firmly fixed with wonkey...

Finally!  ;D Back from the Beach and trying out some Ideas that you guy's have Bounced around "OUT!" this Evening 8)

Im Using BlitzMax 1.5 Vanilla. Ive tried moving to "blitzNG" but i get to many errors and when it finally compile's it dosent work as it should so i stuck with BlitMax 1.5  :-X

Kind Regards to all Baggey!
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

#112
QuoteWe already did video comparation and I found out that Baggey would need 3937 cylcles/msec to run in the same speed like FUSE simulator. When we do this the little running man runs the same speed in both videos. (factor 1.12)

Wow just tried the value of 3937. Title screen is Laggy with Buffer Overrun. However! Ingame music and game emulation seems good! maybe pitch slightly off. When i die, jump or the end game happens im getting a squeeky change in sound!  ;D

So data being sent is happening! and data being recieved is happening!

In my world "Im a SPARKY!" Their out of phase with each other! I think one is leading or lagging the other!  :-\

Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

Okay the latest video for Zx Sound perfection.

In this video i show RingBuffer_1.2 in it's basic form running sound sent by SpecBlitz. I show title music which loses its notes at the end! In game jig which dosent play properly. then i demonstrate Man dying, jumping and end game which is silent!

Second part of video. I make changes to RingBuffer_1.2 to get more functionallity. I scroll through RingBuffer _1.2 altering code to make sound work better being sent from SpecBlitz. Main screen music loses end notes slightly! In game jig sounds good to the ear. In game effects coming through but not write. We can here jumping sort off and end game is audible but not write.

In various test's the best Result's are in SENDING LAST BYTE RECIEVED and also CHUNK_TIME=10 as low as possible the better!?

So again any ideas people? One idea im having is if the buffer is full i should pause Specblitz until the buffer is ready to recieve more bytes?

https://youtu.be/jUwV6YesEHs

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

So, Some more Changes.

For reasons unknown ive lowerd HERTZ, CHUNKTIME is down to 5 and Short sounds have improved?? At the expense of longer playing tune's.
if i have a CHUNKTIME=5 i cant use 44100Hz it crashes.

https://youtu.be/Spju8wsYN5s

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Midimaster

#115
The HERTZ of 44100 are completely wrong! compare the pitch of the song in your video, where FUSE plays the songs. This is massiv higher!!!

You can reach this pitch in yor app only if you rise the HERTZ to 63000.

With 44100 it is to slow and needs to much time.  Why do you test at 44100?

I checked length and pitch of the 4 sounds from your FUSE video in post #97

The Danube-Song  length in FUSE is 20.00 sec
The second music length in FUSE is 13.60 sec
The short Sound  length in FUSE is 00.35 sec
The long Sound   length in FUSE is 02.10 sec


Lets make some examination with the LONG.Mp3
(See attachment)

I made AUDACITY screenshots of FUSE-Samples compared to YOUR-Samples. This is this LONG.MP3 ( the sound appears when the GameOver comes and take the player away)

Here you see a first overview. LONG.MP3 (FUSE) on top  <->  LONGAFTERRINGBUFFER.MP3 (YOURs) at the bottom:

I needed to rise the HERTZ of YOURs to 63.000 to get the same length. Again 63.000!!!

The FUSE sound changes the pitch from low to high.
YOURs looks like sending packages.

Now lets have a deeper look into the samples:


The FUSE has impulses. The distances getting smaller from peak to peak. This causes the rising of the pitch.
YOURs is still a package

Lets look deeper:

The impulses on FUSE are SAWTOOTH


How did this happen? What does it mean?


This means that the Port254 can not only receive a fix HERTZ rate in the game, but can also handle variable frame rate. RingBuffer collected the low rate sended impulses and FreeAudio interpreted it as a short bulk of a 44100 HERTZ audiosample followed by a pause.

But the truth is, that we need to measure the microtime between the impulses and simulate the missing samples, when the rate of impulses is lower than 63000.

Keep the last impuls in mind and send it in a rate of 63000 until the next impuls reaches the PORT. This will result in a SQUARE signal. Not quite perfect but a next step.

So you need to write a function that receive PORT254 impulses and now sends in a given HERTZ rate the last value until a new one arrives.

63000 is our minimum HERTZ, because the "songs" really send 63000 impulses per second.
...on the way to Egypt

Midimaster

#116
This compares to runing man sound of FUSE and YOURs after using the MicroTimer()

It sound better than ever before, but we have a strange pitch effect. YOURs is running faster, but the pitch is lower. Faster would always cause higher pitch. It looks like the original is sending faster, but making pauses between the notes. Do we have forgot someting in the game code?

This effect is only possible if the OUT_254 fires faster for a several time followed by a phase of firing nothing.

Both audacity tracks show exactly the same piece of music (same musical length)

First take is FUSE
below is yours:



Here you see a deeper view into the samples.

Original produces SAWTOOTH, we SQUARE:


I measured the distances:

Result A

In FUSE  the 5 single peaks have a distance of 1.5msec followed of a pause of 77msec

In YOURS  the 5 single peaks have a distance of 2.1msec followed of a pause of 58msec


Result B

In FUSE  the signal is nearly all the time a sequence of 0 and 255.
first (5sample)-package is starting wih 255, the next package with 0, then again the first....


In YOUR  the first signal is a sequence of 0 and 128 ,followed by a sequence of 128 and 0 followed by a sequence of 64 and 255 and so on... it looks chaotic, no system
...on the way to Egypt

Baggey

#117
My values Dont seem to be centered around 0 Volts they seem to be V=sin(wt)+something? so to speak.

If Fuse is tailing of to zero like sawtooth then this may explain why im getting repeating of sounds when there is no more being sent! As were not going to zero?

I think when no more is being sent we need to create a sawtooth function. Maybe interpolate to zero very quickly or just zero. I suppose this is the time for the speaker to settle back to is ready state in the real world. Ie not a perfect square WAVE.

Here are the latest sounds from Manic Miner. Starting to sound like the real thing!

https://youtu.be/4T2oO8pX2dg

Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!

Baggey

Okay, Altered the Timing slightly to compensate.

Wow sounds are working!  :o 8) But cant seem to get rid of the damm repeating! See current Vid.

Anyone any ideas?

Nearly there. https://youtu.be/JXaUDau4gBQ

Kind Regards Baggey
Running a PC that just Aint fast enough!? i7 Quad core 16GB ram 1TB SSD and NVIDIA Quadro K620 . DID Technology stop! Or have we been assimulated!

ZX Spectrum 48k, C64, ORIC Atmos 48K, Enterprise 128K, The SID chip. Im Misunderstood!