Viterbi Encoded Sound Sample

Probably the most technical forum around. It does not have to be coding related, or assembly code only. Just talk about how you can use the AY chip to do cool sounding things :)
User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Viterbi Encoded Sound Sample

Post by jbperin »

Here's my first attempt of replaying a 4kHz viterbi encoded sample on the 3 channels of the AY sound chip.

The original sound file :
SalutToutLeMonde_4k_u8pcm.wav
(7.75 KiB) Downloaded 37 times
The Oric program to play it:
Salut.tap
(26.55 KiB) Downloaded 33 times
(press a key to start and press a key when you've got enough)

Tell me what you think ? do you think it is a good sound quality ?

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

Oups .. I realize I forgot to adapt the encoder to the timing of the replayer.

I think I can enhance the fidelity a little bit.

In fact the encoder takes into account the number of cycle it take for the replayer to write the register into the AY.
I used an approximative value because I didn't know what would the replayer look like when I wrote the encoder.

Now that I have a replayer, I have to calculate the number of cycle between two writing in the AY, and then configure the encoder accordingly.

User avatar
iss
Wing Commander
Posts: 1337
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Viterbi Encoded Sound Sample

Post by iss »

Interesting! ... but IMHO it can be lot better :(.

Just an idea: use the sample WAV from DBug's demo which speaks 'Welcome' (can be found in the OSDK), so we can compare both players. Additionally you can optimize the IRQ routine - you save the registers to ZP *and* save them again with PHA's - use only the first one.

Waiting for the improvements ;)...

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

iss wrote:
Fri Aug 06, 2021 5:44 pm
Just an idea: use the sample WAV from DBug's demo which speaks 'Welcome' (can be found in the OSDK), so we can compare both players.
That's a great idea but I don't have the original wav file.
I've only got the already encoded version :-(
I need the wav file to encode it with the Viterbi stuff. :?
iss wrote:
Fri Aug 06, 2021 5:44 pm
Additionally you can optimize the IRQ routine - you save the registers to ZP *and* save them again with PHA's - use only the first one.
:shock: how the hell do you know that ?? You're exactly right !!

User avatar
iss
Wing Commander
Posts: 1337
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Viterbi Encoded Sound Sample

Post by iss »

jbperin wrote:
Fri Aug 06, 2021 6:17 pm
I need the wav file to encode it with the Viterbi stuff. :?
I can't find the source WAV too. Attached in ZIP file are compiled welcome.tap and 'one-step' moon-landing phrase as tap and 4k 8bit WAV. Hope this helps somehow...
Attachments
samples.zip
(18.66 KiB) Downloaded 30 times

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

iss wrote:
Fri Aug 06, 2021 7:23 pm
I can't find the source WAV too.
Dbug gave me the link of a youtube video of Barbarian 2 which is the game he had taken the "Welcome" from.
I downloaded the audio of the video, extracted the "welcome" and now my computer is encoding the sample (it takes something like 1 hour per second)
I should be able to produce a tap file within a few hour.

iss wrote:
Fri Aug 06, 2021 7:23 pm
Attached in ZIP file are compiled welcome.tap and 'one-step' moon-landing phrase as tap and 4k 8bit WAV. Hope this helps somehow...
Thank you, I will encode it as well.

There's one thing where your help could be very valuable.
As I was inspecting the audio that comes from the Oricutron playing the sample, I noticed some time glitch in the replaying.

Look at the phenomena (top signal is the original signal, bottom is the oricutron audio recorded) at different zoom level:
Sample01.png
Sample02.png
Sample03.png
I've got a keyboard interrupt at 25 HZ which is supposed to be interruptible while the replayer's interrupt at 4kHz is supposed to be uninterruptible

So I wonder where this phenomena comes from ..

Any clue ?

I'm gonna give the source code if you want to cast a glance at it .. if never you could help solve this issue ..

User avatar
iss
Wing Commander
Posts: 1337
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Viterbi Encoded Sound Sample

Post by iss »

jbperin wrote:
Fri Aug 06, 2021 7:59 pm
Any clue ?
IMO, 2 possible sources for the missing samples:
- Oricutron doesn't fill the audio buffer properly - unlikely;
- player code takes too many cycles and misses interrupt signal from time to time.

When you attach test sample I will check it for missing pulses also on real Oric.

EDIT: :idea: can you describe how you write to the 3 volume registers?

User avatar
Dbug
Site Admin
Posts: 3800
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Viterbi Encoded Sound Sample

Post by Dbug »

Sharing the important parts of the code would help :)
Could be all kind of issues, and ultimately it would also be important to compare with a real Oric, just to eliminate possible issues with emulation/host machine.

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

Well, it is very disappointing.

The produced waveform is not so that bad .. but there are some moment where the signal remains flat.

You might be right when you say that some interruption are missed .. but I don't see how I can avoid that :-(

The wecome.tap :
WELCOME.tap
(24.22 KiB) Downloaded 35 times
The source code (with encoder):
ayPlaySampleVit.zip
(385.81 KiB) Downloaded 32 times
The problem that ruins the sound quality:
FlatSignal.png

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

iss wrote:
Fri Aug 06, 2021 8:31 pm
EDIT: :idea: can you describe how you write to the 3 volume registers?
Here's the code of the 4kHz interrupt which writes the AY register values:
It is in the tasks_s.s file in the archive provided in my previous post.

Code: Select all

#define LATCH_REG_NUMBER     sta via_porta:lda #$EE:sta via_pcr:lda #$CC: sta via_pcr
#define LATCH_REG_VALUE      sta via_porta:lda #$EC:sta via_pcr:lda #$CC: sta via_pcr

TASK_4KHZ:
.(
   
    ldy     _position_low

    lda     (_ptr_wrt1), y
    tax
    and     #$F0
    lsr
    lsr
    lsr
    lsr 
    LATCH_REG_NUMBER
    txa
    and     #$0F
    LATCH_REG_VALUE


    lda     (_ptr_wrt2), y
    tax
    and     #$F0
    lsr
    lsr
    lsr
    lsr 
    LATCH_REG_NUMBER
    txa
    and     #$0F
    LATCH_REG_VALUE

    lda     (_ptr_wrt3), y
    tax
    and     #$F0
    lsr
    lsr
    lsr
    lsr 
    LATCH_REG_NUMBER
    txa
    and     #$0F
    LATCH_REG_VALUE

    inc     _position_low

    bne     skipNext256

        inc     _position_high
        inc     _ptr_wrt1+1
        inc     _ptr_wrt2+1
        inc     _ptr_wrt3+1


skipNext256

    lda     _position_low
    cmp     #<NB_SAMPLE 
    bne     skipResume

    lda     _position_high
    cmp     #>NB_SAMPLE
    bne     skipResume

restartsample
	lda #<_bwrt1
	sta _ptr_wrt1
	lda #>_bwrt1
	sta _ptr_wrt1+1

	lda #<_bwrt2
	sta _ptr_wrt2
	lda #>_bwrt2
	sta _ptr_wrt2+1

	lda #<_bwrt3
	sta _ptr_wrt3
	lda #>_bwrt3
	sta _ptr_wrt3+1

	lda #0
	sta _position_low
	sta _position_high

skipResume

task4kHz_done
.)
    rts



User avatar
Dbug
Site Admin
Posts: 3800
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Viterbi Encoded Sound Sample

Post by Dbug »

Some small remarks about the code.

- If you swap the register number and value nibbles in your byte, you can avoid one of the "and #15" because after the four lsr the top nibble would be set to zero (that means three less immediate and, so 6 cycles per IRQ, 480 cycles per frame, almost 2.5% of the total CPU time)

- Make sure your sample is page aligned, so _ptr_wrt1/2/3 are not doing page cross when adding y, to avoid one more cycle per access, which also means on restartsample you could avoid all the lda #<_bwrt1/2/3 because they should just use the same "lda #0" you had at the end

You can also probably simplify the handling of the pointer increments/reset:
- The previous value of _position_low is still in the y register, so the lda _position_low feels a bit unnecessary (instead of the "inc _position_low" (5 cycles) you could "iny / sty _position_low" (2+2 cycles), so remove the lda _position_low and replace the cmp by a cpy)

Now, regarding the Viterbi algorithm, have you implemented the computation of delay between the writing to each of the three registers?

User avatar
iss
Wing Commander
Posts: 1337
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

Re: Viterbi Encoded Sound Sample

Post by iss »

Thanks @Dbug, you shorten my list! :)

Here are some remarks from me:
- you reserve 2 bytes to store the address of old IRQ handler but use:

Code: Select all

    ; Save the old handler value
    lda $245
    sta jmp_old_handler+1 ; <- should be +0
    lda $246
    sta jmp_old_handler+2 ; <- should be +1
- it's VIA T1 specific - to set the period to 250 uS you have to write a value with 4 less i.e.:

Code: Select all

    ;; Set the VIA parameters (250 = 4Khz, )
    lda #<(VIA_TIMER_DELAY_4KHZ-4)
    sta $306 ;; via_t1ll
    lda #>(VIA_TIMER_DELAY_4KHZ-4)
    sta $307 ;; via_t1lh
- now the biggest issue - the time spend in the IRQ handler: TASK_4KHZ takes 220+ uS and if the TASK_25Hz is executed - it takes 968+ uS! Obviously this is the reason for the missing samples ;).
The easiest solution here is to remove the TASK_25Hz (i.e. the keyboard handler) from the IRQ subroutine and move it as polling routine in the main loop.
Once this is fixed then in your IRQ handler called every 250 uS the time is divided as follow:

Code: Select all

irq_handler_4khz:
	....
	jsr TASK_4KHZ
		...
		secval   ; <- here the VOL_A is updated 71 cycles relative to irq_handler_4khz
		....
		....
		thirval   ; <- here the VOL_B is updated 124 cycles relative to irq_handler_4khz (or 53 cycles rel. to secval)
		....
		....
		endval   ; <- here the VOL_C is updated 177 cycles relative to irq_handler_4khz (or 53 cycles rel. to thirval)
	....
	rti  ; <- 220+ cycles		
So, again as @Dbug said: you need to take into account the above delays when pre-calculating register values.
IMHO, there is possible to use an optimization to simplify the code and reduce its size: you can use shorter period 250/3 = ~83 uS and in the handler to write to only one register ;).

I'm really sorry if my remarks sound too critical but I'm sure we can turn this whole thing in something good and useful - don't give up! :)

User avatar
Dbug
Site Admin
Posts: 3800
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Viterbi Encoded Sound Sample

Post by Dbug »

What about replacing

Code: Select all

    lda     (_ptr_wrt1), y
    tax
    lsr   ; 2 cycles
    lsr   ; 2 cycles
    lsr   ; 2 cycles
    lsr    ; 2 cycles
    LATCH_REG_NUMBER
    txa
    and     #$0F
    LATCH_REG_VALUE
by

Code: Select all

    lda     (_ptr_wrt1), y
    tax
    lda TableWithTheNibblesPreshifted,x     ; 4 cycles
    LATCH_REG_NUMBER
    txa
    and     #$0F
    LATCH_REG_VALUE

User avatar
jbperin
Flight Lieutenant
Posts: 377
Joined: Wed Nov 06, 2019 11:00 am
Location: Valence, France

Re: Viterbi Encoded Sound Sample

Post by jbperin »

OK guys !! :-)

I thank you for very much for all your valuables comments.

I took into account all your remarks (except the last one from DBUG that I've just seen (and which look cool)).

Here is the code repository:

https://github.com/jbperin/ayPlaySample

iss wrote:
Sat Aug 07, 2021 12:29 pm
- now the biggest issue - the time spend in the IRQ handler: TASK_4KHZ takes 220+ uS and if the TASK_25Hz is executed - it takes 968+ uS! Obviously this is the reason for the missing samples ;).
The easiest solution here is to remove the TASK_25Hz (i.e. the keyboard handler) from the IRQ subroutine and move it as polling routine in the main loop.
I'm not so sure about that.

I must admit I failed to get the keyboard routine out from the IRQ handler to the main loop. But I added a flag USE_KEYBOARD_INTERRUPT to disable the call to the 25 hz task .. and I noticed no specific amelioration when I use it.
And I'm not so surprised about that because I designed the stuff so that the keyboard dedicated part of the IRQ handler is interruptible and then the 4kHz interrupt allways have priority.
This is why I put the bit $304 just after the jsr TASK_4KHZ and before the 25Hz stuffs in the irq_handler.

Code: Select all

irq_handler_4khz:
.(

	;Preserve registers 
	sta 	irq_A: stx 	irq_X: sty 	irq_Y

	jsr TASK_4KHZ ;  TASK_4KHZ_4BITS ; 

	bit $304

#ifdef USE_KEYBOARD_INTERRUPT
 	dec itCounter: bne not100Hz 

	lda #160: sta itCounter ; 4000 / 25 Hz

	TASK_25Hz

not100Hz	
#endif // USE_KEYBOARD_INTERRUPT

	;Restore Registers 
	lda irq_A: ldx 	irq_X: ldy 	irq_Y

	rti
.)
Moreover, and that's what I would like to bring your attention to, I have analysed the problem and I noticed that:
  • The problem of the flat signal occurs on my Welcome.tap as well as the one of Dbug. (so It might not be due to something specific in my code)
  • The phenomena of signal remaining flat happens on a regular basis and with a repeated pattern
    46 ms of signal,
    6 ms of steady condition,
    46 ms of signal
    6 ms of steady condition,
    92 ms of normal signal
    ... and then it loop ..
On the figure below, I show three different recording of the welcome message:
- the first is the welcome.tap from DBug's demo
- the second is the viterbi welcome.tap with no keyboard handler
- the last one is the viterbi with 25Hz interrupt enabled
FlatPattern.PNG
Can anyone tell me if, when you play the following TAP file in your oricutron:
VITWELC.tap
(24.54 KiB) Downloaded 30 times
You hear something like that:
ViterbiWelcome.mp3
(96.74 KiB) Downloaded 34 times
If not .. could you record for me what you hear ?

User avatar
Dbug
Site Admin
Posts: 3800
Joined: Fri Jan 06, 2006 10:00 pm
Location: Oslo, Norway
Contact:

Re: Viterbi Encoded Sound Sample

Post by Dbug »

jbperin wrote:
Sat Aug 07, 2021 7:44 pm
This is why I put the bit $304 just after the jsr TASK_4KHZ and before the 25Hz stuffs in the irq_handler.

Code: Select all

	;Preserve registers 
	sta 	irq_A: stx 	irq_X: sty 	irq_Y
	jsr TASK_4KHZ ;  TASK_4KHZ_4BITS ; 
	bit $304
If you save registers like that, your IRQ is not reentrant, they will overwrite the status.
For reentrant IRQ you need to use different locations for the various calls, generally done using the stack.

Post Reply