|
Post by ljones on Aug 18, 2012 17:34:08 GMT 1
Hello all Ok I know this is going to sound a little bit weird. But I recently just stumbled over this website; foxular.net/img2wav/On it, it has two perl programs -- both of which do something relatively unusual. One converts a .png image into .wav file; the other perl program does the opposite. I know this sounds like a weird request and after looking at the two perl programs they look to be relatively simple. I even managed to get them to work on my slackware box! Then I suddenly thought -- could these be rewritten in bacon? I've managed to work out how to read simple pictures (such as PPM) before, in fact I once made a program to convert a small .PPM (like a avatar image for example) into forum code. Here's what I came up with; OPEN "1.ppm" FOR READING AS myfile
READLN i1$ FROM myfile READLN i2$ FROM myfile READLN i3$ FROM myfile READLN i4$ FROM myfile
A=INSTR(i3$," ") x$=MID$(i3$,1,A-1) y$=MID$(i3$,A+1,LEN(i3$))
xsize=VAL(x$) ysize=VAL(y$)
FOR y=1 TO ysize FOR x=1 TO xsize
b1=MEMORY(1) GETBYTE b1 FROM myfile SIZE 1 red=PEEK(b1)
b2=MEMORY(1) GETBYTE b2 FROM myfile SIZE 1 green=PEEK(b2)
b3=MEMORY(1) GETBYTE b3 FROM myfile SIZE 1 blue=PEEK(b3)
FREE b1 FREE b2 FREE b3
h1$=HEX$(red) IF red < 16 THEN h1$=CONCAT$("0",h1$) h2$=HEX$(green) IF green < 16 THEN h2$=CONCAT$("0",h2$) h3$=HEX$(blue) IF blue < 16 THEN h3$=CONCAT$("0",h3$)
PRINT "[color="; PRINT "#"; PRINT h1$; PRINT h2$; PRINT h3$; PRINT "]";
PRINT CHR$(226); PRINT CHR$(150); PRINT CHR$(136);
PRINT "[/color]";
NEXT
PRINT
NEXT
CLOSE FILE myfile
Now what I'm thinking is if I can somehow replace the writing to forum-style code to data for a wav file, this idea might work. The only snag is (cue drum roll!) I have no idea on how to create a wav file in bacon! Is there a way to read/write wav's in bacon at all? Thanks BTW Sorry if this post appears more than once. Something went wrong with posting . ljones
|
|
|
Post by Pjot on Aug 18, 2012 19:15:50 GMT 1
Interesting! BaCon has an interface to connect to the Open Audio Library. So I guess your best option to create WAV files is by looking at their documentation... Regards Peter
|
|
|
Post by ljones on Aug 18, 2012 19:58:00 GMT 1
Did not know about that interface, thanks for that ! Will need to look through it all though having looked I wonder if openal allows for "just writing into a file" so to speak, so instead of capturing off a sound card you write the data in via a program. What I'm meaning is this (imaginary code coming up); . .. .. FOR X=0 TO 400 Y%=90+80*SIN(X/20) PRINT#1,CHR$(Y%); NEXT .. ..
I know that's not even proper code, just made up but it produces a sine wave. So write that into a file but as a WAV instead of reading the input from a sound card's line in or mic port. BTW The second line of that is from the Commodore 64 Reference guide. Some things stick long in the memory! ljones
|
|
|
Post by ljones on Aug 18, 2012 21:52:49 GMT 1
I might be already answering my own question. Uh oh! OPEN "test.wav" FOR WRITING AS myfile
REM allocate memory 64K bin=MEMORY(65535)
REM RIFF POKE bin,ASC("R") POKE bin+1,ASC("I") POKE bin+2,ASC("F") POKE bin+3,ASC("F")
REM File length - 8 POKE bin+4,247 POKE bin+5,255 POKE bin+6,0 POKE bin+7,0
REM WAVE POKE bin+8,ASC("W") POKE bin+9,ASC("A") POKE bin+10,ASC("V") POKE bin+11,ASC("E")
REM fmt POKE bin+12,ASC("f") POKE bin+13,ASC("m") POKE bin+14,ASC("t") POKE bin+15,32
REM File length (FMT data = 16 bytes) POKE bin+16,16 POKE bin+17,0 POKE bin+18,0 POKE bin+19,0
REM Format tag (1=PCM) POKE bin+20,1 POKE bin+21,0
REM Channels (1=mono,2=stereo) POKE bin+22,1 POKE bin+23,0
REM Samples per second (68+172*256)=44100 POKE bin+24,68 POKE bin+25,172 POKE bin+26,0 POKE bin+27,0
REM Bytes per second POKE bin+28,136 POKE bin+29,88 POKE bin+30,1 POKE bin+31,0
REM Block Align POKE bin+32,2 POKE bin+33,0
REM bits 8 or 16 POKE bin+34,16 POKE bin+35,0
REM "DATA" POKE bin+36,ASC("d") POKE bin+37,ASC("a") POKE bin+38,ASC("t") POKE bin+39,ASC("a")
REM length of data block POKE bin+40,255 POKE bin+41,255 POKE bin+42,0 POKE bin+43,0
start=bin+44 end=bin+65535-44 FOR J=start TO end RR=RANDOM(32767) PRINT RR POKE J,RR NEXT
PUTBYTE bin TO myfile SIZE 65535
CLOSE FILE myfile
Note that on one page I linked to above the offset at 28 is called "bytes/second" and says "sample rate * block align". On the other page I found it described as "Byterate" and "SampleRate * NumChannels * BitsPerSample/8", that's the one I used. Same for the next one "Blockalign" too. That program will create a wav file (noise) as I found some useful infos here ( www.lightlink.com/tjweber/StripWav/Canon.html also ccrma.stanford.edu/courses/422/projects/WaveFormat/ ) . I had imagined the wav file format to be a lot more complex than this! Only other problems were being able to convert long and normal integers into bytes. For 4 byte integers ("longs") I had to temporarily revert back to dosbox/qbasic and use (uh oh) qbasic's MKL$ command. I came up with this to work out the values for byterate and blockalign; REM test CLS
REM Work out the values for Byterate and Blockalign on WAV files.
REM Samplerate (e.g. 44100) samplerate = 44100
REM Number of channels (1=mono,2=stereo) numchannels = 1
REM Bits used per sample (8 or 16) bitspersample = 16
byterate = samplerate * numchannels * bitspersample / 8 Blockalign = numchannels * bitspersample / 8
A$ = MKL$(byterate)
PRINT "Byterate="; byterate FOR A = 1 TO LEN(A$) B$ = MID$(A$, A, 1) PRINT ASC(B$); NEXT
PRINT PRINT PRINT "Blockalign="; Blockalign
HI = INT(Blockalign / 256) LO = Blockalign - HI * 256 PRINT LO,HI
This helped (qbasic x.x) to convert long integers to bytes; b=65535 a$=mkl$(b) for t=1 to len(a$) b$=mid$(a$,t,1) print asc(b$); next
Or integer to byte; x=2 hi=int(x/256) lo=x-hi*256 print lo,hi
So ..... far I'm a little further along! The next problem? Working out how to deal with signed integers (-32767 to 32768) in the data! .....You see from what I can gather I can't use signed integers in bacon's memory commands so I need to go from signed toi unsigned (and back). ljones
|
|
|
Post by ljones on Aug 19, 2012 14:46:54 GMT 1
Just a little further on. The following modification seemed to provide a relatively good sine wave - as a test.
This first line goes at the top;
GLOBAL s TYPE float
And then this replaces the "random" part of the code;
s=0
FOR J=start TO end STEP 2 s=s+0.1 RR=150+22000*SIN(s/8) HI=INT(RR/256) LO=RR-HI*256 PRINT RR; PRINT " "; PRINT s POKE J,LO POKE J+1,HI NEXT
Should write a reasonably good sine wave into a wav file. It plays as a very low-pitched sound. At this stage I'm not sure if I need to make what I've written into memory above (poke j,lo etc) a signed integer or not.
ljones
|
|
|
Post by ljones on Aug 19, 2012 20:07:10 GMT 1
unfortunatly I'm possibly going to have to forget the idea. Here's what I got so far though it dosen't work. Really I don't know enough to do this. PRINT "Opening 1.ppm" OPEN "1.ppm" FOR READING AS myfile1
PRINT "Opening test.wav" OPEN "test.wav" FOR WRITING AS mywavfile
FUNCTION MKL$(NUMBER value) C1=POW(2,24) C2=POW(2,16) C3=POW(2,8) byte1=value / C1 & 255 byte2=value / C2 & 255 byte3=value / C3 & 255 byte4=value & 255 a1$=CHR$(byte4) a2$=CHR$(byte3) a3$=CHR$(byte2) a4$=CHR$(byte1) a5$=CONCAT$(a1$,a2$,a3$,a4$) RETURN a5$ END FUNCTION
PRINT "Counting bytes" REM count the bytes READLN i1$ FROM myfile1 READLN i2$ FROM myfile1 READLN i3$ FROM myfile1 READLN i4$ FROM myfile1 A=INSTR(i3$," ") x$=MID$(i3$,1,A-1) y$=MID$(i3$,A+1,LEN(i3$)) xsize=VAL(x$) ysize=VAL(y$) FOR y=1 TO ysize FOR x=1 TO xsize b1=MEMORY(1) GETBYTE b1 FROM myfile1 SIZE 1 red=PEEK(b1) b2=MEMORY(1) GETBYTE b2 FROM myfile1 SIZE 1 green=PEEK(b2) b3=MEMORY(1) GETBYTE b3 FROM myfile1 SIZE 1 blue=PEEK(b3) FREE b1 FREE b2 FREE b3 filesize=filesize+6 NEXT NEXT CLOSE FILE myfile1
PRINT "The filesize is in bytes "; PRINT filesize
PRINT "Allocate memory" bin=MEMORY(filesize)
DATA 82,73,70,70 DATA 0,0,0,0 DATA 87,65,86,69 DATA 102,109,116,32 DATA 16,0,0,0 DATA 1,0 DATA 1,0 DATA 68,172,0,0 DATA 136,88,1,0 DATA 2,0 DATA 16,0 DATA 68,65,84,65 DATA 0,0,0,0
PRINT "Poking 43 byte wav header" FOR count=0 TO 43 READ data POKE bin+count,data PRINT "Byte "; PRINT count; PRINT " "; NEXT count
PRINT PRINT
PRINT "filesize1/2" filesize1=filesize-8 filesize2=filesize-43
PRINT "Poking file length" REM file length-8 A$=MKL$(filesize1) FOR J=1 TO 4 B$=MID$(A$,J,1) POKE bin+3+J,ASC(B$) PRINT J; PRINT " "; PRINT bin+3+J NEXT J
PRINT
PRINT "poking file length (2)" REM filelength-44 A$=MKL$(filesize2) FOR J=1 TO 4 B$=MID$(A$,J,1) POKE bin+39+J,ASC(B$) PRINT J; PRINT " "; PRINT bin+3+J NEXT J
PRINT
start=bin+44
PRINT "Poking wave data now="; PRINT start PRINT
REM Poke data OPEN "1.ppm" FOR READING AS myfile1 READLN i1$ FROM myfile1 READLN i2$ FROM myfile1 READLN i3$ FROM myfile1 READLN i4$ FROM myfile1 A=INSTR(i3$," ") x$=MID$(i3$,1,A-1) y$=MID$(i3$,A+1,LEN(i3$)) xsize=VAL(x$) ysize=VAL(y$)
FOR y=1 TO ysize FOR x=1 TO xsize b1=MEMORY(1) GETBYTE b1 FROM myfile1 SIZE 1
red=PEEK(b1) hi=INT(red/256) lo=red-hi*256 POKE start,lo POKE start+1,hi start=start+2
b2=MEMORY(1) GETBYTE b2 FROM myfile1 SIZE 1
green=PEEK(b2) hi=INT(green/256) lo=green-hi*256 POKE start,lo POKE start+1,hi start=start+2
b3=MEMORY(1) GETBYTE b3 FROM myfile1 SIZE 1 blue=PEEK(b3)
hi=INT(blue/256) lo=blue-hi*256 POKE start,lo POKE start+1,hi start=start+2
FREE b1 FREE b2 FREE b3 NEXT NEXT
PRINT "Closing file" CLOSE FILE myfile1
PRINT "Write data" PUTBYTE bin TO mywavfile SIZE filesize CLOSE FILE mywavfile
PRINT "filesize is" PRINT filesize
Half the problem is the original is in perl and uses perl modules and I'm basically having to reimplement half of perl or so it seems. Ah well. . I did see something called libsndfile though I have no idea on how to use it. ljones
|
|
|
Post by Pjot on Aug 20, 2012 20:07:22 GMT 1
Well, that is not completely untrue... BaCon is just starting and a lot of interfaces need to be developed. If you want to volunteer, go ahead Thanks for your efforts so far! Regards Peter
|
|