How to Read a .wav file or other audio file
Hi, Not sure this is the right place to ask but I am trying to find a way of reading audio signal from a .wav file in lpcm format into an array or data file rather than for playing so that I can present audio waves in a visual form or to analyse the signal in voice recognition or modifing the sound. If anyone can help or point me in the right direction I'd be grateful.
Thanks Richard W.
Thanks Richard W.
0
Comments
-
I am trying to find a way of reading audio signal from a .wav file in lpcm format into an array or data file
There are several ways this could be approached, some using only native BBC BASIC code and others relying on functions in (for example) the SDL2 library.
The native-code approach relies on knowing that a WAV file has a header with a well-defined format. So I would start by defining a structure corresponding to that header (caution: this code isn't compatible with lowercase keywords):DIM wav{riff%, total%, wave%, fmt%, fmtsize%, wFormatTag{l&,h&}, nChannels{l&,h&}, \ \ nSamplesPerSec%, nAvgBytesPerSec%, nBlockAlign{l&,h&}, wBitsPerSample{l&,h&}, \ \ data%, datasize%}
Having defined the header format, you can read a corresponding amount from the start of the file, most conveniently into a string:wav% = OPENIN(wavfile$) IF wav% = 0 .... REM handle the case when the file couldn't be opened header$ = GET$#wav% BY DIM(wav{})
Then point the structure to what has been read from the file:PTR(wav{}) = PTR(header$)
Now you can conveniently read the parameters of the file directly from the structure, for example:PRINT "Sampling rate = "; wav.nSamplesPerSec%; " samples per second"
At this point you can handle the actual audio data any way you want, either by loading it all into memory if it will fit (remember than you can raise HIMEM) or loading only a 'chunk' at a time if it won't.
Hopefully this will have given you some ideas, at least.
0 -
Great thanks for that. I'll experiment with that ..Thanks again0
-
Hi Richard,
Thanks again for your suggestions. I spent some time trying to make sense of the raw .wav data in a recording I made using the recorder in the bbcsdl20 examples folder. I finally read up a bit more on pcm formatting... I think my file (Aliens.wav) has two, 2 byte audio channels, interleaved, with the most significant bit as the sign bit. I graphed the output, as shown by screenshots below
I used this code to load the header as you suggested
wavfile$="fours/Aliens1.wav"
DIM wav{riff%, total%, wave%, fmt%, fmtsize%, wFormatTag{l&,h&}, nChannels{l&,h&}, \
\ nSamplesPerSec%, nAvgBytesPerSec%, nBlockAlign{l&,h&}, wBitsPerSample{l&,h&}, \
\ data%, datasize%}
wav% = OPENIN(wavfile$)
IF wav% = 0 THEN PRINT "Could not load File: ";wavfile$ :PRINT ERR:STOP
header$ = GET$#wav% BY DIM(wav{})
PTR(wav{}) = PTR(header$)
I used the code below to load the data from the file after reading the header
LR=0
REPEAT PLS=PLS+1
PULSE$(PLS,0)=GET$#wav% BY 2
LR=1+PLS MOD 2
PULSE$(PLS,LR)=FNSTR2VAL(LEFT$(PULSE$(PLS,0),2))
UNTILPLS>999999 OR EOF#wav%
CLOSE#wav%
.......
........
STOP
DEF FNSTR2VAL(AB$)
LXV=0
CODSUM=0
SSGN=0
FOR ZXZ=1 TO 130:PVQ$(ZXZ)="":NEXT
REM NUMBERING RIGHTMOST BYTE AS ZERO THEN WORKING LEFT, BYTENUM =0,1,2,3 ETC ..
REM THEN MULTIPLYING THE ASCII CODE OF EACH BYTE BY 256^(BYTENUM)
BBN2=ASC(MID$(AB$,1,1))
IF BBN2>=128 THEN
REM CONVERTING RAW BINARY IN STRING INTO AN ACTUAL SIGNED DECIMAL VALUE
REM FROM 1111111111111111 (-32767) TO 01111111111111111 (+32767) MSB = SIGN BIT
SSGN=-1
NEG=NEG+1
ELSE
SSGN=1
ENDIF
FOR LXX=LEN(AB$) TO 1 STEP -1
LLXX=LEN(AB$)-LXX
IF SSGN=1 THEN
PVQ$(LXX)=STR$(ASC(MID$(AB$,LXX,1)))
CODSUM=ASC(MID$(AB$,LXX,1))*(256^(LLXX))+CODSUM
ENDIF
IF SSGN=-1 THEN
REM REMOVING THE SIGNBIT (MSB OF THE 2 BYTES)
IF LXX=1 THEN
BBN3=(ASC(MID$(AB$,1,1))-128)
MID$(AB$,1,1)=CHR$(BBN3)
ENDIF
PVQ$(LXX)=STR$(ASC(MID$(AB$,LXX,1)))
CODSUM=ASC(MID$(AB$,LXX,1))*(256^(LLXX))+CODSUM
ENDIF
NEXT LX
IF SSGN<>0 THEN CODSUM=CODSUM*SSGN
PVQ$(0)=STR$(CODSUM)
=PVQ$(0)
hope this is ok?
My objective is to write code that can identify numbers from short sections of speech. This could be well be too ambitious but worth a try anyway. If you have any suggestions, that could be very useful. I have learned so much so far.
Thanks.
0