Saving a wave pattern to a .WAV file

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Saving a wave pattern to a .WAV file

Post by rbytes »

This line is producing an error. Where is the function defined?

Code: Select all

wav_file_stereo(2*N3,stereo,S,8,"out.wav")
I have the Jan 10 versions of wav_util and signal_util. They do not list such a function.
The only thing that gets me down is gravity...

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Saving a wave pattern to a .WAV file

Post by Henko »

Sloppy source management!! :cry:

Code: Select all

' .WAV related functions, version january 10, 2018
' def wav(m$)
' def wav_info(m$,xs,ys,ww,hh,R,G,B,alpha)
' def wav_file(n_bytes,s(),n_channels,s_rate,bps,file$)
' def wav_add_stream(file$,ns,str(),max_value)
' def wav_file_stereo(n_bytes,s(),s_rate,bps,file$)
' def hertz(t$)
' def num2hex4(x,a())

def wav(m$)
dim t(4)
file m$ readdim t,n,4 ! f_riff$=""
for i=0 to 3 ! f_riff$ &= chr$(t(i)) ! next i
file m$ readdim t,n,4 ! f_size=0
for i=0 to 3 ! f_size += t(i)*256^i ! next i
file m$ readdim t,n,4 ! f_wave$=""
for i=0 to 3 ! f_wave$ &= chr$(t(i)) ! next i
file m$ readdim t,n,4 ! f_fmt$=""
for i=0 to 3 ! f_fmt$ &= chr$(t(i)) ! next i
file m$ readdim t,n,4 ! fmt_size=0
for i=0 to 3 ! fmt_size += t(i)*256^i ! next i
file m$ readdim t,n,2 ! audio_fmt=t(0)+t(1)*256
file m$ readdim t,n,2 ! num_channels=t(0)+t(1)*256
file m$ readdim t,n,4 ! sample_rate=0
for i=0 to 3 ! sample_rate += t(i)*256^i ! next i
file m$ readdim t,n,4 ! byte_rate=0
for i=0 to 3 ! byte_rate += t(i)*256^i ! next i
file m$ readdim t,n,2 ! block_align=t(0)+t(1)*256
file m$ readdim t,n,2 ! bits_per_sample=t(0)+t(1)*256
if fmt_size>16 then file m$ readdim t,n,fmt_size-16
file m$ readdim t,n,4 ! f_data$=""
for i=0 to 3 ! f_data$ &= chr$(t(i)) ! next i
file m$ readdim t,n,4 ! data_size=0
for i=0 to 3 ! data_size += t(i)*256^i ! next i
start_data_adress=44
end def

def wav_info(m$,xs,ys,ww,hh,R,G,B,alpha)
dim w$(14)
wav(m$)
name$="wavinfo"
page name$ set 
page name$ frame xs,ys,ww,hh
page name$ color R,G,B,alpha
button "w_close" title "❎" at ww-30,5 size 24,22
set buttons custom ! draw color 0,0,0
button "bottom" title "" at -6,hh-3 size ww+12,3
button "left" title "" at 0,-6 size 3,hh+12
button "right" title "" at ww-3,-6 size 3,hh+12
button "upper1" title "" at -6,0 size ww+12,3
button "upper2" title "" at -6,30 size ww+12,3
field "tt" text "info: " & m$ at 20,7 size ww-60,20 RO
field "tt" back color R,G,B ! field "tt" font color 0,0,1
field "tt" back alpha alpha
w$(1)="File descriptor     : "      & wav.f_riff$
w$(2)="File size                : " & wav.f_size
w$(3)="Format type         : "      & wav.f_wave$
w$(4)="Fmt ident.             : "   & wav.f_fmt$
w$(5)="Fmt chunk size    : "        & wav.fmt_size
w$(6)="Audio format        : "      & wav.audio_fmt
w$(7)="# of channels       : "      & wav.num_channels
w$(8)="Sample rate          : "     & wav.sample_rate
w$(9)="Byte rate               : "  & wav.byte_rate
w$(10)="Block align            : "  & wav.block_align
w$(11)="Bits per sample    : "      & wav.bits_per_sample
w$(12)="Data block ident   : "      & wav.f_data$
w$(13)="Data block size     : "     & wav.data_size
for i=1 to 13
  fd$="w"&i
  field fd$ text w$(i) at 10,15+25*i size ww-20,25 RO
  field fd$ back color R,G,B ! field fd$ font color 0,0,0
  field fd$ back alpha alpha
  next i
wait: while not button_pressed("w_close") ! goto wait ! end while
page name$ hide
end def

' function to encapsulate a series of samples in a .WAV file.
' the sample values are normalized to integers in the 0-255 range.
' n_bytes = the number of sample values in the sample array s().
' n_channels = the number of (parallel) channels
' s_rate = the sample rate (8000, 11025, 44100, etc)
' bps = bits per sample
' file$ = the .WAV file to wich the data are to be saved.
'
def wav_file(n_bytes,s(),n_channels,s_rate,bps,file$)
if file_exists(file$) then file file$ delete
ob=option_base() ! option base 0
dim snd(n_bytes),out(44),x(4)
bmax=-1000000 ! bmin=1000000 
for i=0 to n_bytes-1 
  bmax=max(bmax,s(i)) ! bmin=min(bmin,s(i))
  next i
fac=255/(bmax-bmin) ! bps=8  ' as long as normalization to 255
for i=0 to n_bytes-1
  snd(i)=s(i)-bmin ! snd(i)=floor(fac*snd(i))
  next i
restore to dat1
for i=0 to 43 ! read out(i) ! next i
b_rate=n_channels*bps/8*s_rate
num2hex4(n_bytes+36,x)     ' file size
for i=0 to 3 ! out(i+4)=x(i) ! next i
num2hex4(n_channels,x)  ' number of channels
for i=0 to 1 ! out(i+22)=x(i) ! next i
num2hex4(s_rate,x)      ' sample rate
for i=0 to 3 ! out(i+24)=x(i) ! next i
num2hex4(b_rate,x)      ' byte rate
for i=0 to 3 ! out(i+28)=x(i) ! next i
num2hex4(bps,x)         ' bits per sample
for i=0 to 1 ! out(i+34)=x(i) ! next i
num2hex4(n_bytes,x)  ' chunk size
for i=0 to 3 ! out(i+40)=x(i) ! next i
file file$ writedim out,44,0
file file$ writedim snd,n_bytes,0
file file$ setpos 0
dat1:
data 82,73,70,70,0,0,0,0,87,65,86
data 69,102,109,116,32,16,0,0,0,1,0
data 1,0,0,0,0,0,0,0,0,0,1
data 0,8,0,100,97,116,97,0,0,0,0
option base ob
end def

' add a byte stream (samples) to an existing .wav file
' the stream is appended to the last existing subchunk in the file
' hence the stream will be interpreted accordingly
' the data are normalized between 0 and max_value
'
def wav_add_stream(file$,ns,str(),max_value)
ob=option_base() ! option base 0
dim x(4)
if odd(ns) or not file_exists(file$) then return 0
bmax=-1000000 ! bmin=1000000 ! max_value=min(255,max_value)
for i=0 to ns-1 
  bmax=max(bmax,str(i)) ! bmin=min(bmin,str(i))
  next i
fac=max_value/(bmax-bmin)
for i=0 to ns-1
  str(i)-=bmin ! str(i)=floor(fac*str(i))
  next i
wav(file$)
fs=wav.f_size+ns ! ds=wav.data_size+ns
file file$ setpos 4
num2hex4(fs,x) ! file file$ writedim x,4,0
file file$ setpos 40
num2hex4(ds,x) ! file file$ writedim x,4,0
file file$ setpos wav.f_size+8
file file$ writedim str,ns,0
option base ob
file file$ setpos 0
return 1
end def

' function to encapsulate a stereo stream in a .WAV file.
' the sample values are normalized to integers in the 0-255 range.
' n_bytes = the number of sample values in the sample array s().
' s_rate = the sample rate (8000, 11025, 44100, etc)
' bps = bits per sample
' file$ = the .WAV file to wich the data are to be saved.
'
def wav_file_stereo(n_bytes,s(),s_rate,bps,file$)
if file_exists(file$) then file file$ delete
ob=option_base() ! option base 0
dim snd(n_bytes),out(44),x(4)
bmax=-1000000 ! bmin=1000000 
for i=0 to n_bytes-1 
  bmax=max(bmax,s(i)) ! bmin=min(bmin,s(i))
  next i
fac=255/(bmax-bmin) ! bps=8  ' as long as normalization to 255
for i=0 to n_bytes-1
  snd(i)=s(i)-bmin ! snd(i)=floor(fac*snd(i))
  next i
for i=0 to 43 ! read out(i) ! next i
b_rate=2*bps/8*s_rate
num2hex4(n_bytes+36,x)     ' file size
for i=0 to 3 ! out(i+4)=x(i) ! next i
num2hex4(s_rate,x)      ' sample rate
for i=0 to 3 ! out(i+24)=x(i) ! next i
num2hex4(b_rate,x)      ' byte rate
for i=0 to 3 ! out(i+28)=x(i) ! next i
num2hex4(bps,x)         ' bits per sample
for i=0 to 1 ! out(i+34)=x(i) ! next i
num2hex4(n_bytes,x)  ' chunk size
for i=0 to 3 ! out(i+40)=x(i) ! next i
file file$ writedim out,44,0
file file$ writedim snd,n_bytes,0
file file$ setpos 0
data 82,73,70,70,0,0,0,0,87,65,86
data 69,102,109,116,32,16,0,0,0,1,0
data 2,0,0,0,0,0,0,0,0,0,2
data 0,8,0,100,97,116,97,0,0,0,0
option base ob
end def

' function that returns the frequency for a given note
' the frequency is given with one decimal precision
' input format as defined by Rbytes in his post dd. jan. 4, 2018
' uppercase and lowercase note digits are accepted
' octave number range is from 0 through 9
' if an octave number is present, a global octave number will be set
' if an octave number is missing, the global value will be taken
' # or $, when present, must be the second token in the input
' in case of an error in the input, the value 0 is returned
'
def hertz(t$)
ob=option_base() ! option base 0
tl=len(t$) ! if tl=0 or tl>3 then return 0
c$=capstr$(left$(t$,1)) ! if c$<"A" or c$>"G" then return 0
rnr=asc(c$)-67 ! if rnr<0 then rnr+=7
rnr*=2 ! if rnr>5 then rnr-=1
if tl=1 then label2
m$=mid$(t$,1,1)
if not (m$="#" or m$="$") then
  octnum=val(m$) ! goto label1
  end if
if m$="#" then rnr+=1 else rnr-=1
if tl=3 then octnum=val(right$(t$,1)) else goto label2
label1: if octnum<0 or octnum>9 then return 0
.octave=octnum
label2: octnum=.octave
option base ob
return int(275*2^(octnum+(rnr-9)/12))/10
end def

def num2hex4(x,a())
a(0)=0 ! a(1)=0 ! a(2)=0 ! a(3)=0
f1=256 ! f2=f1*f1 ! f3=f1*f2
a(3)=floor(x/f3)
if a(3) then x-=a(3)*f3
a(2)=floor(x/f2)
if a(2) then x-=a(2)*f2
a(1)=floor(x/f1)
if a(1) then x-=a(1)*f1
a(0)=x
return
end def


User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Saving a wave pattern to a .WAV file

Post by rbytes »

No problem. Now I get a stereo sound file, but the sound on the left seems to be a low-pitched noise rather than a chord in the designated octave. Here is my out.wav file. Does it sound like yours?
out.wav
(12.93 KiB) Downloaded 360 times
The only thing that gets me down is gravity...

Henko
Posts: 814
Joined: Tue Apr 09, 2013 12:23 pm
My devices: iPhone,iPad
Windows
Location: Groningen, Netherlands
Flag: Netherlands

Re: Saving a wave pattern to a .WAV file

Post by Henko »

You are right. The chord stream is "stretched" by a factor of three, because it must last as long as the three individual notes. As the sample rate is the same for the chord and the notes, Hence the frequency must be augmented by a factor three, see the piece of code hereafter. The sound is now correct.

Code: Select all

' *** GENERATE CHORD SIGNAL
sine_signal(N3,chord,100,3*hertz("c4"),0,0,"0")
sine_signal(N3,chord,100,3*hertz("f"),0,0,"+")
sine_signal(N3,chord,100,3*hertz("a"),0,0,"+")

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Saving a wave pattern to a .WAV file

Post by rbytes »

Sounds great now. Thanks. 8-)
The only thing that gets me down is gravity...

Post Reply