Here follows a first try for defining and playing chords.
Would you try out different chords in the "Definition of a chord" section, and hear if correct chords are produced by the speaker?
Also note, that i have packed several functions in a new "wav_util" library. The code follows the testprogram for chords.
Code: Select all
pi=4*atan(1)
' INPUT DATA
S=4000 ' sample rate for .WAV file
T=2 ' duration of tone in seconds
F=440 ' frequency of a tone
' CALCULATED DATA
N=T*S ' # of bytes for one tone in a chord
C=T*F ' # of cycles for function sine_wave()
N3=3*N ' # of bytes for a chord of three tones
dim tone1(N),tone2(N),tone3(N),sig(N3)
' DEFINITION OF A CHORD
sine_signal(N,tone1,100,T*hertz("C5"),0,0,"0")
sine_signal(N,tone2,100,T*hertz("e"),0,0,"0")
sine_signal(N,tone3,100,T*hertz("a"),0,0,"0")
for i=0 to N-1
sig(3*i)=tone1(i) ! sig(3*i+1)=tone2(i) ! sig(3*i+2)=tone3(i)
next i
f$="test.wav"
wav_file_chord(N3,sig,3,S,8,f$)
play_music(f$)
end
' 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_chord(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
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
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,3
data 0,8,0,100,97,116,97,0,0,0,0
option base ob
end def
def play_it(mus$)
music m$ load mus$
ml=music_length(m$)
music m$ play
pause ml
end def
{signal_util} ' code to be found in a post dd dec.4,2016
' def sine_signal(N,v(),ampl,freq,shift,vdc,mode$)
' def saw_signal(N,v(),ampl,freq,shift,vdc,mode$)
' def tri_signal(N,v(),ampl,freq,shift,vdc,mode$)
' def block_signal(N,v(),ampl,freq,shift,vdc,mode$)
' def noise(N,v(),ampl,distr$,mode$)
' def hex2dec(h$)
' def dec2hex$(num,npos)
' def h2d(h$)
' def d2h$(num)
' def play_music(mus$)
' def wav(m$)
' def wav_info(m$,xs,ys,ww,hh,R,G,B,alpha)
' def r_fft(N,x(),reX(),imX())
' def c_fft(M,x())
' def graph(txt$,N,v(),ytop,sc)
' def graph_magn(M,rx(),ix(),ytop)
' def sigstat(N,v(),st())
' def box(ytop)
' def box2(ytop)
' def cntrl(xs,ys)
' def sbar(xs,ys,ww,ss,sw)
' def b_p(b$)
{wav_util} ' .WAV related functions
' 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 hertz(t$)
' def num2hex4(x,a())
Code: Select all
' 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 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
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
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 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