Convert WAV files to Zero Crossing Audio using BASIC [message #373308] |
Wed, 05 September 2018 11:58 |
|
Originally posted by: frank_o_rama
I've implemented a method to convert 16-bit WAV files directly from Audacity to zero crossing (COMPUTE! audio player) format using BASIC. The WAV must be mono and at the same sample rate as the player (7,500Hz). You can do a sample playback in Audacity by selecting all audio and doing "Effect-->Amplify", setting it to maximum and turning on "Allow Clipping".
f
5 REM CONVERT WAV TO ZERO CROSSING AUDIO
10 FILE$ = "I.LUV.7100.WAV"
REM FILENAME OF WAV FILE - 7100Hz sample rate
20 N = 2530218
REM NUMBER OF BYTES IN WAV FILE
25 OUT$ = "I.LUV.7100.ZC"
REM OUTPUT FILENAME
30 PREV = 0:BC = 7:X = 0:POKE 8194,0
REM ZERO OUT PREVIOUS READING, RESET BIT COUNT, RESET NEW FILE OFFSET
40 FOR W = 44 TO N STEP 2
REM LOOP TO END, SKIP WAV METADATA, TOP BYTE OF 16-BIT ONLY
50 PRINT CHR$(4)"BLOAD "FILE$",T$00,A$2000,L1,B"W
60 BYTE = PEEK(8192)
REM READ BYTE AT CURRENT POSITION
70 IF BYTE < 129 THEN CUR = 0
80 IF BYTE > 128 THEN CUR = 1
100 IF CUR = 0 AND PREV = 0 THEN BIT = 0:PREV = 0:GOTO 140
110 IF CUR = 0 AND PREV = 1 THEN BIT = 1:PREV = 0:GOTO 140
120 IF CUR = 1 AND PREV = 0 THEN BIT = 1:PREV = 1:GOTO 140
130 IF CUR = 1 AND PREV = 1 THEN BIT = 0:PREV = 1:GOTO 140
140 PRINT W" "CUR" "BIT" "BC
150 IF BIT = 1 THEN NB = PEEK(8194)+(2^BC):POKE 8194,NB
160 BC=BC-1
170 IF BC=-1 THEN X=X+1:PRINT CHR$(4)"BSAVE "OUT$",A$2002,L1,B"X:BC=7:POKE 8194,0
180 NEXT
|
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373320 is a reply to message #373312] |
Wed, 05 September 2018 19:18 |
|
Originally posted by: frank_o_rama
You'll probably want to set your emulator to "MAXIMUM SPEED". haha. I converted a 2 1/2 minute song in about 45 minutes. Code golf away.
I'll have to look at my WAV file format notes again. I think there's a field early on which tells the offset the data starts at.
The filename is 7100 because the ZC audio player I'm working on runs at 7100 Hz sample rate. The COMPUTE! player/recorder program runs at 7500 Hz (Mine checks for keypress). You can adjust the exported sample rate in Audacity to work at any sample rate, and get a preview of the final output.
F
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373322 is a reply to message #373320] |
Wed, 05 September 2018 20:59 |
Michael J. Mahon
Messages: 1767 Registered: October 2012
Karma: 0
|
Senior Member |
|
|
<frank_o_rama@hotmail.com> wrote:
> You'll probably want to set your emulator to "MAXIMUM SPEED". haha. I
> converted a 2 1/2 minute song in about 45 minutes. Code golf away.
>
> I'll have to look at my WAV file format notes again. I think there's a
> field early on which tells the offset the data starts at.
>
> The filename is 7100 because the ZC audio player I'm working on runs at
> 7100 Hz sample rate. The COMPUTE! player/recorder program runs at 7500 Hz
> (Mine checks for keypress). You can adjust the exported sample rate in
> Audacity to work at any sample rate, and get a preview of the final output.
>
> F
>
This is one of those cases where a short assembly language program would be
about 1000 times faster—in the processing, not the I/O.
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
|
|
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373337 is a reply to message #373326] |
Thu, 06 September 2018 01:41 |
Michael J. Mahon
Messages: 1767 Registered: October 2012
Karma: 0
|
Senior Member |
|
|
Tom Porter <laseractiveguy@gmail.com> wrote:
> You need every speed boot you can get.
> I didnt see BYTE used for anthing else, so put it out of the loop.
> Also CUR=0 always, eliminates a comparison.
> 40 BYTE = PEEK(8192): FOR W = 44 TO N STEP 2
> 60
> 70 CUR=0:IF BYTE>128 THEN CUR=1
> 80
>
Opening two files for each sample processed makes ProDOS the bottleneck.
First step would be to process, say, 16 blocks of 16-bit samples to 1 block
of zero crossings. That should make the Applesoft code the bottleneck, at
many times the current speed.
Then would be a good time to look at the code.
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
|
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373354 is a reply to message #373320] |
Thu, 06 September 2018 15:35 |
|
Originally posted by: Tom Porter
Frank,
What are the results that you are achieving... I have converted 3 'small' sound clips and they come up nothing but static. I've tried all 9 speeds in compute's recorder playback.
Here is the method I used... (in audacity/cider press/apple win)
1. (FILE MENU) TRACKS - STERO TO MONO
2. PROJECT RATE (HZ) AT BOTTOM LEFT... CHANGE TO 7500
3. EXPORT FILE AS 16BIT WAV
4. IMPORT TO PRODOS DISK... RUN PROGRAM TO CONVERT
5. CHANGE FILENAMES IN 10,25 AND FILE SIZE IN 20 (for #4)
6. PLAY WITH COMPUTE MAGAZINE ARTICAL DRIVER
|
|
|
Convert WAV files to Zero Crossing Audio using BASIC [message #373355 is a reply to message #373308] |
Thu, 06 September 2018 16:01 |
Michael AppleWin Debu
Messages: 1262 Registered: March 2013
Karma: 0
|
Senior Member |
|
|
There are numerous optimizations we can do to that Applesoft reference converter.
1. The obvious low-hanging fruit of micro-optimizations include:
* Cache the partial BLOAD and BSAVE strings
* BYTE is redundant, just set CUR directly
* Replace obtuse BIT = CUR XOR PREV using a pure math replacement. See my "Boolean Floating Point Logic" shader for more details: https://www.shadertoy.com/view/lsXyDH
5 REM CONVERT WAV TO ZERO CROSSING AUDIO
6 I = 8192: REM INPUT BYTE
7 A = 8194: REM OUTPUT BYTE
10 FILE$ = "I.LUV.7100.WAV"
15 R$ = CHR$(4) + "BLOAD " + FILE$ + ",T$00,A" + I + ",L1,B"
20 N = 2530218
25 OUT$ = "I.LUV.7100.ZC"
26 W$ = CHR$(4) + "BSAVE " +OUT$ + ",A" + A + ",L1,B"
30 PREV = 0:BC = 7:X = 0:POKE A,0
40 FOR W = 44 TO N STEP 2
50 PRINT R$;W
60 CUR = PEEK(8192) > 128:BIT = CUR*(1 - PREV) + PREV*(1-CUR):PREV = CUR
140 PRINT W" "CUR" "BIT" "BC
150 IF BIT = 1 THEN N = PEEK(A)+(2^BC):POKE A,N
160 BC=BC-1
170 IF BC<0 THEN X=X+1:PRINT W$;X:BC=7:POKE A,0
180 NEXT
* I would also replace all variables longer then 2 chars due to Applesoft having a bug/feature that they are all treated the same. i.e. Replace CUR with C, etc.
5 REM CONVERT WAV TO ZERO CROSSING AUDIO
6 I = 8192: REM INPUT BYTE
7 A = 8194: REM OUTPUT BYTE
10 I$ = "I.LUV.7100.WAV"
15 R$ = CHR$(4) + "BLOAD " + I$ + ",T$00,A" + I + ",L1,B"
20 N = 2530218
25 O$ = "I.LUV.7100.ZC"
26 W$ = CHR$(4) + "BSAVE " + O$ + ",A" + A + ",L1,B"
30 V = 0:C = 7:X = 0:POKE A,0
40 FOR W = 44 TO N STEP 2
50 PRINT R$;W
60 U = PEEK(8192) > 128:V = U*(1 - V) + V*(1-U):V = U
140 PRINT W" "U" "V" "C
150 IF V THEN N = PEEK(A)+(2^C):POKE A,N
160 C=C-1
170 IF C<0 THEN X=X+1:PRINT W$;X:C=7:POKE A,0
180 NEXT
2. Since this program is horribly inefficient, that is, 99.99% I/O bound due to reading and writing 1 byte at a time, it would be far faster to read in chunks, such as 8192, byte at a time. I'll provide a solution next week.
Michael
|
|
|
Convert WAV files to Zero Crossing Audio using BASIC [message #373356 is a reply to message #373355] |
Thu, 06 September 2018 16:50 |
Michael AppleWin Debu
Messages: 1262 Registered: March 2013
Karma: 0
|
Senior Member |
|
|
Whoops, would help if I used the proper var names =P
5 REM CONVERT WAV TO ZERO CROSSING AUDIO
6 I = 8192: REM INPUT BYTE
7 A = 8194: REM OUTPUT BYTE
10 I$ = "I.LUV.7100.WAV"
15 R$ = CHR$(4) + "BLOAD " + I$ + ",T$00,A" + I + ",L1,B"
20 N = 2530218
25 O$ = "I.LUV.7100.ZC"
26 W$ = CHR$(4) + "BSAVE " + O$ + ",A" + A + ",L1,B"
30 V = 0:C = 7:X = 0:POKE A,0
40 FOR W = 44 TO N STEP 2
50 PRINT R$;W
60 U = PEEK(I) > 128:B = U*(1 - V) + V*(1-U):V = U
140 PRINT W" "U" "B" "C
150 IF B THEN N = PEEK(A)+(2^C):POKE A,N
160 C=C-1:IF C<0 THEN X=X+1:PRINT W$;X:C=7:POKE A,0
180 NEXT
Legend:
A = Output Address
B = Bit Value
C = Bit Count
I = Input Address
N = Byte Value
U = Current Byte
V = Previous Byte
W = Input Offset
X = Output Offset
|
|
|
Convert WAV files to Zero Crossing Audio using BASIC [message #373357 is a reply to message #373356] |
Thu, 06 September 2018 17:11 |
Michael AppleWin Debu
Messages: 1262 Registered: March 2013
Karma: 0
|
Senior Member |
|
|
Since Applesoft multiplication is dog-slow and BIT only has 2 states we care about ...
IF CUR = 0 THEN BIT = PREV
IF CUR = 1 THEN BIT = 1 - PREV
.... we can replace XOR with this faster variant:
60 U = PEEK(I) > 128:B = U:IF U THEN B=1-V
70 V = U
5 REM CONVERT WAV TO ZERO CROSSING AUDIO
6 I = 8192: REM INPUT BYTE
7 A = 8194: REM OUTPUT BYTE
10 I$ = "I.LUV.7100.WAV"
15 R$ = CHR$(4) + "BLOAD " + I$ + ",T$00,A" + I + ",L1,B"
20 N = 2530218
25 O$ = "I.LUV.7100.ZC"
26 W$ = CHR$(4) + "BSAVE " + O$ + ",A" + A + ",L1,B"
30 V = 0:C = 7:X = 0:POKE A,0
40 FOR W = 44 TO N STEP 2
50 PRINT R$;W
60 U = PEEK(I) > 128:B = U:IF U THEN B=1-V
70 V = U:IF B THEN N = PEEK(A)+(2^C):POKE A,N
80 C=C-1:IF C<0 THEN X=X+1:PRINT W$;X:C=7:POKE A,0
90 NEXT
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373358 is a reply to message #373354] |
Thu, 06 September 2018 17:13 |
|
Originally posted by: frank_o_rama
Tom,
It's a little tricky. Audacity makes you change both the project bitrate (bottom left) as well as the track bitrate (File-->Tracks-->Resample...). I think you need to change the track bitrate FIRST (menu), then the project bitrate (lower corner). That's how I got it to work. Otherwise it will sound like alvin and the chipmunks.
When you export, be sure to REMOVE any metadata (hit "Clear" in the dialogue box). You may have to experiment with where the actual data starts, also. It will still work but you may have a bit of noise at the start. Change the "44" in line 40 of the converter to adjust the offset. You can also look at the raw data with a hex editor like "Hex Fiend" if you're on macOS.
Also, once you have a final "ZC" file, you will need to load it into chunks if it's longer than available memory... ie...
5 HOME
10 ?CHR$(4)"BLOAD PLAYER.APP"
15 FOR A = 0 TO 158136 STEP 35328
20 ?CHR$(4)"BLOAD I.LUV.7100.ZC,A$C00,L$8A00,B"A
25 ? A
30 CALL 768 : REM LAUNCH PLAYER
35 NEXT A
40 END
If your player is using other parts of memory, change A$ and L$ values in line 20, as well as STEP value in line 15. This will play a whole song. Apologies for the not-so-detailed writeup.
f
On Thursday, September 6, 2018 at 12:36:00 PM UTC-7, Tom Porter wrote:
> Frank,
>
> What are the results that you are achieving... I have converted 3 'small' sound clips and they come up nothing but static. I've tried all 9 speeds in compute's recorder playback.
>
> Here is the method I used... (in audacity/cider press/apple win)
> 1. (FILE MENU) TRACKS - STERO TO MONO
> 2. PROJECT RATE (HZ) AT BOTTOM LEFT... CHANGE TO 7500
> 3. EXPORT FILE AS 16BIT WAV
> 4. IMPORT TO PRODOS DISK... RUN PROGRAM TO CONVERT
> 5. CHANGE FILENAMES IN 10,25 AND FILE SIZE IN 20 (for #4)
> 6. PLAY WITH COMPUTE MAGAZINE ARTICAL DRIVER
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373359 is a reply to message #373308] |
Thu, 06 September 2018 17:13 |
|
Originally posted by: frank_o_rama
Here are my notes about the WAV file format. Seems to be offset at 44 bytes if you clear the metadata.
1st 4 bytes are the words "RIFF" $52 49 46 46
next 4 bytes are the size of the chunk data (not including these bytes, or the "RIFF")
next 4 bytes are "WAVE" $57 41 56 45 (this is the start of the WAV chunk)
next 4 bytes are "fmt " (note space) $66 6D 74 20
next 4 bytes are the bit depth of the samples???? ($10 00 00 00 = 16)
next 4 bytes ???? ($01 00 01 00 = 65537) signed data? mono sample rate?
next 4 bytes are the sample rate = $11 2B 00 00 = $00002B11 = 11025(Hz) (offsets 24-28)
next 4 bytes are sample rate (stereo)?? $22 56 00 00 = 22050 (Hz?)
next 4 bytes ???? ($02 00 01 00 = 1048578 stereo sample rate?
next 4 bytes are "data" = $64 61 74 61 (offsets 36-40)
next 4 bytes are the size of the following data chunk
begin actual sample info directly after (offset 44)
|
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373362 is a reply to message #373354] |
Thu, 06 September 2018 18:58 |
Michael J. Mahon
Messages: 1767 Registered: October 2012
Karma: 0
|
Senior Member |
|
|
Tom Porter <laseractiveguy@gmail.com> wrote:
> Frank,
>
> What are the results that you are achieving... I have converted 3 'small'
> sound clips and they come up nothing but static. I've tried all 9 speeds
> in compute's recorder playback.
>
> Here is the method I used... (in audacity/cider press/apple win)
> 1. (FILE MENU) TRACKS - STERO TO MONO
> 2. PROJECT RATE (HZ) AT BOTTOM LEFT... CHANGE TO 7500
> 3. EXPORT FILE AS 16BIT WAV
> 4. IMPORT TO PRODOS DISK... RUN PROGRAM TO CONVERT
> 5. CHANGE FILENAMES IN 10,25 AND FILE SIZE IN 20 (for #4)
> 6. PLAY WITH COMPUTE MAGAZINE ARTICAL DRIVER
It may help reduce the noise level to add a small amount to the high byte
of each sample before taking its high bit. This displaces the threshold
enough to make low-volume noise not create “zero crossings”.
Increasing the volume of the sampled sound may also help (but may require
raising the “zero” threshold even more).
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373363 is a reply to message #373358] |
Thu, 06 September 2018 18:58 |
Michael J. Mahon
Messages: 1767 Registered: October 2012
Karma: 0
|
Senior Member |
|
|
<frank_o_rama@hotmail.com> wrote:
>
> Tom,
>
> It's a little tricky. Audacity makes you change both the project bitrate
> (bottom left) as well as the track bitrate (File-->Tracks-->Resample...).
> I think you need to change the track bitrate FIRST (menu), then the
> project bitrate (lower corner). That's how I got it to work. Otherwise it
> will sound like alvin and the chipmunks.
>
> When you export, be sure to REMOVE any metadata (hit "Clear" in the
> dialogue box). You may have to experiment with where the actual data
> starts, also. It will still work but you may have a bit of noise at the
> start. Change the "44" in line 40 of the converter to adjust the offset.
> You can also look at the raw data with a hex editor like "Hex Fiend" if you're on macOS.
>
> Also, once you have a final "ZC" file, you will need to load it into
> chunks if it's longer than available memory... ie...
>
> 5 HOME
> 10 ?CHR$(4)"BLOAD PLAYER.APP"
> 15 FOR A = 0 TO 158136 STEP 35328
> 20 ?CHR$(4)"BLOAD I.LUV.7100.ZC,A$C00,L$8A00,B"A
> 25 ? A
> 30 CALL 768 : REM LAUNCH PLAYER
> 35 NEXT A
> 40 END
>
> If your player is using other parts of memory, change A$ and L$ values in
> line 20, as well as STEP value in line 15. This will play a whole song.
> Apologies for the not-so-detailed writeup.
>
> f
Or you can export the sound as a “raw” 8-bit unsigned file—no prefix, and
half the file size of 16-bit samples. Don’t worry about the “unsigned”, the
high bit still has the same significance as a sign bit, just reversed
polarity (which doesn’t matter).
>
>
> On Thursday, September 6, 2018 at 12:36:00 PM UTC-7, Tom Porter wrote:
>> Frank,
>>
>> What are the results that you are achieving... I have converted 3
>> 'small' sound clips and they come up nothing but static. I've tried all
>> 9 speeds in compute's recorder playback.
>>
>> Here is the method I used... (in audacity/cider press/apple win)
>> 1. (FILE MENU) TRACKS - STERO TO MONO
>> 2. PROJECT RATE (HZ) AT BOTTOM LEFT... CHANGE TO 7500
>> 3. EXPORT FILE AS 16BIT WAV
>> 4. IMPORT TO PRODOS DISK... RUN PROGRAM TO CONVERT
>> 5. CHANGE FILENAMES IN 10,25 AND FILE SIZE IN 20 (for #4)
>> 6. PLAY WITH COMPUTE MAGAZINE ARTICAL DRIVER
>
>
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373364 is a reply to message #373361] |
Thu, 06 September 2018 19:32 |
Michael AppleWin Debu
Messages: 1262 Registered: March 2013
Karma: 0
|
Senior Member |
|
|
> 60 u=peek(i)>128:b=u*(1-v)
> or would that be counter effective?
I suspect the FP multiplication would be slower then the IF-THEN test, but I haven't profiled Applesoft to know.
But, sadly, I have a typo in that last optimization that broke the XOR. :-/
i.e. Recall the original code:
100 IF CUR = 0 AND PREV = 0 THEN BIT = 0:PREV = 0:GOTO 140
110 IF CUR = 0 AND PREV = 1 THEN BIT = 1:PREV = 0:GOTO 140
120 IF CUR = 1 AND PREV = 0 THEN BIT = 1:PREV = 1:GOTO 140
130 IF CUR = 1 AND PREV = 1 THEN BIT = 0:PREV = 1:GOTO 140
Which can be replaced with these two lines of an optimized BIT = CUR XOR PREV
100 BIT = PREV: IF CUR THEN BIT = 1 - PREV
110 PREV = CUR
The correct optimized line is:
60 U = PEEK(I) > 128: B = V: IF U THEN B = 1 - V
Third time's the charm? :-)
Shame that Applesoft didn't provide an XOR token/operator on the ][+, //e.
|
|
|
Re: Convert WAV files to Zero Crossing Audio using BASIC [message #373367 is a reply to message #373364] |
Thu, 06 September 2018 20:41 |
Michael J. Mahon
Messages: 1767 Registered: October 2012
Karma: 0
|
Senior Member |
|
|
Michael 'AppleWin Debugger Dev' <michael.pohoreski@gmail.com> wrote:
>> 60 u=peek(i)>128:b=u*(1-v)
>> or would that be counter effective?
>
> I suspect the FP multiplication would be slower then the IF-THEN test,
> but I haven't profiled Applesoft to know.
It is.
> But, sadly, I have a typo in that last optimization that broke the XOR. :-/
>
> i.e. Recall the original code:
>
> 100 IF CUR = 0 AND PREV = 0 THEN BIT = 0:PREV = 0:GOTO 140
> 110 IF CUR = 0 AND PREV = 1 THEN BIT = 1:PREV = 0:GOTO 140
> 120 IF CUR = 1 AND PREV = 0 THEN BIT = 1:PREV = 1:GOTO 140
> 130 IF CUR = 1 AND PREV = 1 THEN BIT = 0:PREV = 1:GOTO 140
>
> Which can be replaced with these two lines of an optimized BIT = CUR XOR PREV
>
> 100 BIT = PREV: IF CUR THEN BIT = 1 - PREV
> 110 PREV = CUR
>
> The correct optimized line is:
>
> 60 U = PEEK(I) > 128: B = V: IF U THEN B = 1 - V
>
> Third time's the charm? :-)
>
> Shame that Applesoft didn't provide an XOR token/operator on the ][+, //e.
>
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
|
|
|