"Ohne Dich": Play digital audio from tape in real-time
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
"Ohne Dich": Play digital audio from tape in real-time
This piece is supposed to play a pulse width modulated tune from tape at four bits resolution. Sampling rates of up to 6kHz are possible without additional distortion.
4kHz version with some geek trying to sing:
PAL version: http://hugbox.org/pixel/software/vic-20 ... ch_pal.zip
NTSC version: http://hugbox.org/pixel/software/vic-20 ... h_ntsc.zip
Another version with a well–known jump'n-run theme:
PAL version: http://hugbox.org/pixel/software/vic-20/mario_pal.zip
NeverTheSameColor version: http://hugbox.org/pixel/software/vic-20/mario_ntsc.zip
A preview package of both tunes at 6kHz sampling rate is laying around here:
http://hugbox.org/pixel/external/denial/ohne_dich6k.zip
4kHz version with some geek trying to sing:
PAL version: http://hugbox.org/pixel/software/vic-20 ... ch_pal.zip
NTSC version: http://hugbox.org/pixel/software/vic-20 ... h_ntsc.zip
Another version with a well–known jump'n-run theme:
PAL version: http://hugbox.org/pixel/software/vic-20/mario_pal.zip
NeverTheSameColor version: http://hugbox.org/pixel/software/vic-20/mario_ntsc.zip
A preview package of both tunes at 6kHz sampling rate is laying around here:
http://hugbox.org/pixel/external/denial/ohne_dich6k.zip
Last edited by pixel on Sun Apr 17, 2016 11:34 am, edited 1 time in total.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
The timer is now self-adjusting at the cost of sound quality. IMHO there's no way around that.
All files have been updated again.
All files have been updated again.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
Re: "Ohne Dich": Play digital audio from tape in real-time
I thought only one bit was possible...?
PRG Starter - a VICE helper / Vic Software (Boray Gammon, SD2IEC music player, Vic Disk Menu, Tribbles, Mega Omega, How Many 8K etc.)
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
It's pulse width modulated. So, this thing uses 16 different pulse lengths. And now it constantly calculates the average pulse width to keep the needle in place.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
Here's the code from the first version without timer adjustment. Things quite fell into place at ~4kHz.
EDIT: Removed a leftover "tax".
Code: Select all
average_loop_cycles = @(half (+ 4 2 2 3))
sure_delay = 7
timer = @(- (* 8 audio_longest_pulse) average_loop_cycles sure_delay)
tape_audio_player:
; Start tape motor.
lda $911c
and #$fd
sta $911c
; Initialize VIA2 timer 1.
ldx #0 ; one-shot mode
stx $912b
lda #<timer
sta $9124
ldy #>timer
; Play.
f: lda $9121 ; Reset the VIA2 CA1 status bit.
l: lda $912d ; (4) Read the VIA2 CA1 status bit.
lsr ; (2) Shift to test bit 2.
lsr ; (2) Could be "and #2" but these uneven cycles dither the output nicely.
bcc -l ; (2/3) Nothing happened yet. Try again…
lda $9124 ; (4) Read the timer's low byte which is your sample.
sty $9125 ; (4) Write high byte to restart the timer.
lsr ; Reduce sample from 7 to 4 bits.
lsr
lsr
sta $900e ; Play it!
sta $900f ; Something for the eye.
jmp -f
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
OK. I guess it won't get any better. My flatmate's brain has been formatted with the Super Mario theme, so I'll get dragged back into life anyhow. Here's the version with self-adjustment. If anybody would go through the trouble of testing the TAPs on a real machine – that would be lovely!
Code: Select all
current_low = 4
average = 5
tleft = 7
average_loop_cycles = @(half (+ 4 2 2 3))
sure_delay = 7
timer = @(- (* 8 audio_longest_pulse) average_loop_cycles sure_delay)
tape_audio_player:
; Start tape motor.
lda $911c
and #$fd
sta $911c
; Initialize VIA2 timer 1.
ldx #0 ; one-shot mode
stx $912b
a: lda #0
sta tleft
sta average
sta @(++ average)
lda #<timer ; Set to countdown from longest pulse length in theory.
sta current_low
ldy #>timer
; Play.
f: lda $9121 ; (4) Reset the VIA2 CA1 status bit.
l: lda $912d ; (4) Read the VIA2 CA1 status bit.
lsr ; (2) Shift to test bit 2.
lsr ; (2)
bcc -l ; (2/3) Nothing happened yet. Try again…
lda $9124 ; (4) Read the timer's low byte which is your sample.
sty $9125 ; (4) Write high byte to restart the timer.
tax
lsr ; (2) Reduce sample from 7 to 4 bits.
lsr ; (2)
lsr ; (2)
sta $900e ; (4) Play it!
sta $900f ; (4) Something for the eye.
; Make sum of samples of which we'll draw the average later on.
txa
clc
adc average
sta average
bcc +n
inc @(++ average)
bne -f ; (unconditional jump)
n:
; Make the great divide if we've summed up 128 samples.
dec tleft
bne -f
; Correct timer if average pulse length doesn't match our desired value.
s: lda @(++ average) ; average / 256
tax
cmp #$29 ; 41… why? Should be 64.
beq +j
bcc +n
dec current_low
bne +d ; (unconditional jump)
n: inc current_low
d: lda current_low
sta $9124
; Divide average by 128 and restart summing up samples.
j: txa
asl
sta average
lda #0
rol
sta @(++ average)
lda #128
sta tleft
bne -f ; (another unconditional jump)
Last edited by pixel on Tue Apr 28, 2015 1:56 pm, edited 1 time in total.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- freshlamb
- Vic 20 Dabbler
- Posts: 76
- Joined: Sun Apr 04, 2004 5:38 pm
- Website: http://www.rufnoiz.com
- Location: Prince Albert SK Can
Re: "Ohne Dich": Play digital audio from tape in real-time
Works exactly the way you said it would for the NTSC version on a real Vic! I will post video when I get a chance.
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
YES!!1!!!1! Wanna see it! Thanks 1E6!
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
Freshlamb: I was just wondering how you got the thing on tape and what type of tape you used. If somebody converts one of those TAPs to an audio file with 48kHz sampling rate it'd end up with less than three bits per sample. My thinking is that I'd have to get one of those sexy SD2IEC devices and to code a tape writer to get it done for real.
The original intent was to also put on some video as well. But before you're totally convinced that I'm off-the-map nuts: back in the days it was almost no problem to record 4.8kbits/s on an Amstrad CPC464 tape drive and what we have here is some kind of analogue recording that ignores errors.
Anybody an idea what the physical limits are?
The original intent was to also put on some video as well. But before you're totally convinced that I'm off-the-map nuts: back in the days it was almost no problem to record 4.8kbits/s on an Amstrad CPC464 tape drive and what we have here is some kind of analogue recording that ignores errors.
Anybody an idea what the physical limits are?
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
I've put 48kHz WAV files for the tapes online as well.
Turn down the volume before playing these like regular music unless you want a new haircut!
http://hugbox.org/pixel/software/vic-20 ... al.wav.zip
http://hugbox.org/pixel/software/vic-20 ... sc.wav.zip
http://hugbox.org/pixel/software/vic-20 ... al.wav.zip
http://hugbox.org/pixel/software/vic-20 ... sc.wav.zip
Turn down the volume before playing these like regular music unless you want a new haircut!
http://hugbox.org/pixel/software/vic-20 ... al.wav.zip
http://hugbox.org/pixel/software/vic-20 ... sc.wav.zip
http://hugbox.org/pixel/software/vic-20 ... al.wav.zip
http://hugbox.org/pixel/software/vic-20 ... sc.wav.zip
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- freshlamb
- Vic 20 Dabbler
- Posts: 76
- Joined: Sun Apr 04, 2004 5:38 pm
- Website: http://www.rufnoiz.com
- Location: Prince Albert SK Can
Re: "Ohne Dich": Play digital audio from tape in real-time
I used AudioTap to convert, Wavelab for any adjusting, and just recorded on my tape deck. So perhaps there is a degrading of the sound. Here is a video link. https://www.youtube.com/watch?v=PahhRvIVdVM
Re: "Ohne Dich": Play digital audio from tape in real-time
Rock Band for the Vic 20. Coming soon.
Sent from my phizzone
Sent from my phizzone
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
Thany you for that wonderful video! I'm seriously baffled about it working at all on a real machine… I had to sleep over it first. Boray probably has no idea how many days and nights his player has been running here as an inspiration.
I didn't really understand what's going on in the last few seconds of the video, though.
If you want to hack in your own samples they have to be 4-bit, as you might have guessed, but they also have got to be unsigned. Then add $18 to each sample and, voila, you have the TAP data. The "sox" audio converter gave me terrible results, so I'm actually converting 16-bit samples myself. Don't let your audio converter dither the samples! They're are dithered by the player already! Also, a lowpass filter at 2kHz, as suggested by boray, is a real quality enhancer. Another problem: "Ohne Dich" rumbles a lot, because the bass is too strong. Last but not least a compander brings back silent passages. Writing the player was no problem in matters of time – but converting the music took _ages_!
I'm super-glad because this brings "Pulse" close to a tape release. An SD2IEC is on it's way now (I hope) to write the tapes.
Yeah! Vic Band! Teeheeheeh! For SD2IEC and tape, please! I guess disk drives won't be of much help?
I didn't really understand what's going on in the last few seconds of the video, though.
If you want to hack in your own samples they have to be 4-bit, as you might have guessed, but they also have got to be unsigned. Then add $18 to each sample and, voila, you have the TAP data. The "sox" audio converter gave me terrible results, so I'm actually converting 16-bit samples myself. Don't let your audio converter dither the samples! They're are dithered by the player already! Also, a lowpass filter at 2kHz, as suggested by boray, is a real quality enhancer. Another problem: "Ohne Dich" rumbles a lot, because the bass is too strong. Last but not least a compander brings back silent passages. Writing the player was no problem in matters of time – but converting the music took _ages_!
I'm super-glad because this brings "Pulse" close to a tape release. An SD2IEC is on it's way now (I hope) to write the tapes.
Yeah! Vic Band! Teeheeheeh! For SD2IEC and tape, please! I guess disk drives won't be of much help?
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- freshlamb
- Vic 20 Dabbler
- Posts: 76
- Joined: Sun Apr 04, 2004 5:38 pm
- Website: http://www.rufnoiz.com
- Location: Prince Albert SK Can
Re: "Ohne Dich": Play digital audio from tape in real-time
Probably around the same time you were making your player (because I have no SDIEC) I was wondering if I could make samples play from memory, so that is what the last part of the video is. Just me experimenting.
I looked at the code for your player, and have yet to wrap my head around it. Because I use synths I vaguely understand PWM, but I'm not sure how it applies. At any rate the player is very, very cool. I want to try the new WAV's you put up, as soon as I can.
I looked at the code for your player, and have yet to wrap my head around it. Because I use synths I vaguely understand PWM, but I'm not sure how it applies. At any rate the player is very, very cool. I want to try the new WAV's you put up, as soon as I can.
- pixel
- Vic 20 Scientist
- Posts: 1342
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: "Ohne Dich": Play digital audio from tape in real-time
I'm afraid the VIA chip isn't explained in very enjoyable ways anywhere.
Had to grab a sheet of paper and lay out the register and bits myself to
get it in.
The two VIAs have two timers each that count down at the speed of the CPU
clock. Timer 2 in each chip has the advantage that it has "latches". If
you write the low byte of the timer, it goes into the latch without
affecting the timer. As soon as you write the high byte the timer is set
to the written values, counting down. If you set the timer to 256 on a NTSC
VIC it'll count down to 0 in 1027270 / 256 = 1/4013s.
Fortunately, the timers can also be read.
The VIA can tell you if the signal from tape went low – the end of a
pulse; that's that status bit. It has to be reset manually.
Now, that's all we need. The recorded pulses look like this:
We need the minimum pulse width to actually output the samples and to
do the bookkeeping. More about that later on.
Now for the actual playing. We set the timer to the longest pulse length of
210. When the minimum pulse width has passed the timer counted down to
128. When the pulse stops a little bit later we get some value from 120
to 127. That shifted three bits to the right gives us the sample value 15.
When the status bit signals that the pulse ended we just read the low byte
of the timer, immediately reset the timer by writing its high byte, then we
shift the value we've just read and output it.
That's where the trouble starts. One cannot assume that all tape drives
have the same speed and we need some way to adjust the maximum pulse length
somehow. If we calculate the average value of all samples, we get the sample
value that lies on the center of our audio wave. The timer should've counted
down to 64 if the timing was perfect. (Sure as hell that's only the case in
VICE.) If the average timer value is above our desired value, we decrement
the longest pulse width or we increment it or we leave it alone when it's
right. BUT you have to take the time into account that is not measured
from the point when the status bit isn't yet detected (average loop cycles)
and the sure time not measured until the timer is restarted. Maybe that's
why the desired average is 41, not 64.
How the average is calculated isn't very obvious since the player isn't
initialized properly. Since it's self-adjusting it simply doesn't have to
be. It sums up the last 256 samples in chunks of 128 to let the former
averages flow in, so the change would be gradual. I've no bloody clue
about mathematics. It just hit me on the throne and it works. Might also
a flaw in this algorithm that skewed the desired average sample.
I'm sure that everything will be explained some day.
Had to grab a sheet of paper and lay out the register and bits myself to
get it in.
The two VIAs have two timers each that count down at the speed of the CPU
clock. Timer 2 in each chip has the advantage that it has "latches". If
you write the low byte of the timer, it goes into the latch without
affecting the timer. As soon as you write the high byte the timer is set
to the written values, counting down. If you set the timer to 256 on a NTSC
VIC it'll count down to 0 in 1027270 / 256 = 1/4013s.
Fortunately, the timers can also be read.
The VIA can tell you if the signal from tape went low – the end of a
pulse; that's that status bit. It has to be reset manually.
Now, that's all we need. The recorded pulses look like this:
Code: Select all
192 cycles | 128 cycles max.
------------------------FEDCBA9876543210 <- sample values for each 8
| | variable | extra cycles
| minimum pulse width | additional |
| | width |
Longest pulse is 310 cycles. ---------->
Average is 256 cycles ---------->
+
| +
| +
| +
| +
| +
| +
|+
+ <- our audio wave
+|
+ |
+ |
+ |
+ |
+ |
+ |
+|
do the bookkeeping. More about that later on.
Now for the actual playing. We set the timer to the longest pulse length of
210. When the minimum pulse width has passed the timer counted down to
128. When the pulse stops a little bit later we get some value from 120
to 127. That shifted three bits to the right gives us the sample value 15.
When the status bit signals that the pulse ended we just read the low byte
of the timer, immediately reset the timer by writing its high byte, then we
shift the value we've just read and output it.
That's where the trouble starts. One cannot assume that all tape drives
have the same speed and we need some way to adjust the maximum pulse length
somehow. If we calculate the average value of all samples, we get the sample
value that lies on the center of our audio wave. The timer should've counted
down to 64 if the timing was perfect. (Sure as hell that's only the case in
VICE.) If the average timer value is above our desired value, we decrement
the longest pulse width or we increment it or we leave it alone when it's
right. BUT you have to take the time into account that is not measured
from the point when the status bit isn't yet detected (average loop cycles)
and the sure time not measured until the timer is restarted. Maybe that's
why the desired average is 41, not 64.
How the average is calculated isn't very obvious since the player isn't
initialized properly. Since it's self-adjusting it simply doesn't have to
be. It sums up the last 256 samples in chunks of 128 to let the former
averages flow in, so the change would be gradual. I've no bloody clue
about mathematics. It just hit me on the throne and it works. Might also
a flaw in this algorithm that skewed the desired average sample.
I'm sure that everything will be explained some day.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose