Saving a wave pattern to a .WAV file
- 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:
- Contact:
Re: Saving a wave pattern to a .WAV file
Maybe a better suggestion is an interpreter such as Smart Basic uses to play MIDI notes. This could be adapted from the note-naming conventions used by SB. I will quote them, but leave out any parameters that are not relevant at this time:
•letters "C", "D", "E", "F", "G", "A", "B" are notes "do", "re", "mi", "fa", "sol", "la", "si"
•letter "R" is a rest
•characters "#" and "$" make sharp and flat notes: C#, D$
•octave is a number after note: E3, D#5
•letters "W", "H", "Q", "I", "S", "T" are duration of following notes, where "W"=whole, "H"=half, "Q"=quarter, "I"=eighth, "S"=sixteenth, "T"=thirty second, "X"=sixty fourth, "Y"=one hundred twenty eighth: HC#
•character "." means that next note is one and a half times longer: Q.C
•chord is set with notes in round brackets: (EGB)
•octave number, note duration are not necessary to specify for each and every note - they affect all following notes until the value is changed
Users could then generate music and save it as a wave file.
•letters "C", "D", "E", "F", "G", "A", "B" are notes "do", "re", "mi", "fa", "sol", "la", "si"
•letter "R" is a rest
•characters "#" and "$" make sharp and flat notes: C#, D$
•octave is a number after note: E3, D#5
•letters "W", "H", "Q", "I", "S", "T" are duration of following notes, where "W"=whole, "H"=half, "Q"=quarter, "I"=eighth, "S"=sixteenth, "T"=thirty second, "X"=sixty fourth, "Y"=one hundred twenty eighth: HC#
•character "." means that next note is one and a half times longer: Q.C
•chord is set with notes in round brackets: (EGB)
•octave number, note duration are not necessary to specify for each and every note - they affect all following notes until the value is changed
Users could then generate music and save it as a wave file.
The only thing that gets me down is gravity...
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Saving a wave pattern to a .WAV file
Not sure about the added value of your proposal, but may be fun to code it. It reminds me of our 'datamine' project.
Anyhow, here is an basic function that returns the frequency for any note in your format.
Next i'll make a more elegant scrollable list window for picking notes.
Anyhow, here is an basic function that returns the frequency for any note in your format.
Next i'll make a more elegant scrollable list window for picking notes.
Code: Select all
print hertz("d$0"),hertz("A4"),hertz("f")
end
' 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 any 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
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Saving a wave pattern to a .WAV file
A function "wav_add_stream() has been added. Using this function enables appending a stream of bytes (one note in this case) to an already existing .WAV file. The stream is appended to the already present subchunk in the file, hence the new stream will be interpreted according to the already present (monochannel) specifications.
One of the next steps will be the ability to add entire subchunks, together with their own specifications (should be possible).
One of the next steps will be the ability to add entire subchunks, together with their own specifications (should be possible).
Code: Select all
N=4000 ! pi=4*atan(1)
dim sig(N),song$(4)
' *** filename for the piece of art to be created
f$="Father Jacob.wav"
' *** read the notes for the song
for i=0 to 3 ! read song$(i) ! next i
data "c4","d","e","c"
' *** generate the first note
sine_signal(N,sig,100,hertz(song$(0)),0,0,"0")
' *** encapsulate in a new .WAV file
wav_file(N,sig,1,4000,8,f$)
' *** generate the other notes and append them to the existing file
for i=1 to 3
sine_signal(N,sig,100,hertz(song$(i)),0,0,"0")
wav_add_stream(f$,N,sig,255)
next i
' *** play it
play_music(f$)
' *** add another tone to the file and play it again
block_signal(N,sig,100,hertz("F#5"),0,0,"0")
wav_add_stream(f$,N,sig,255)
pause .5 ! play_music(f$)
' *** show header info
wav_info(f$,100,100,300,500,.7,.7,.7,1)
end
' 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 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
def play_it(mus$)
music m$ load mus$
ml=music_length(m$)
music m$ play
pause ml
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
{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$)
- 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:
- Contact:
Re: Saving a wave pattern to a .WAV file
Well done! Melodies can now be played, with all notes of equal length. If the sb MIDI format is followed, the next step would be a final letter indicating the duration of each note, or a final period to extend the duration by 50%. The desired pitch of the note currently changes with each change of timing, so N would need a compensating adjustment to prevent this.
The only thing that gets me down is gravity...
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Saving a wave pattern to a .WAV file
Yes, i noticed that today. Must have a deeper look into that.
- 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:
- Contact:
Re: Saving a wave pattern to a .WAV file
I tried creating a variable nd for note duration. That works well, as you can see in this modified code. It loops 5 times. First the song is played in whole notes, then half notes, quarters, eighths and sixteenths.
In addition to changing the value of N, I divide the frequency returned by the hertz function by nd. Otherwise it would double each time N is halved.
This gets us partway there, but there is still the need to be able to set and read a duration for each note, so that rhythms can be played.
In addition to changing the value of N, I divide the frequency returned by the hertz function by nd. Otherwise it would double each time N is halved.
This gets us partway there, but there is still the need to be able to set and read a duration for each note, so that rhythms can be played.
Code: Select all
/*
Wave Song Generator
by Henko January 2018
All notes are of equal length
Set nd to the note duration desired, in powers of 2
1=whole, 2=half, 4=quarter, 8=eighth, 16=sixteenth
*/
dim sig(8000),song$(4)
' play the song in whole, half, quarter, eighth and sixteenth notes
for t=0 to 4
restore
nd=2^t
text clear
print "nd =";nd
N=8000/nd ! pi=4*atan(1)
' *** filename for the piece of art to be created
f$="Father Jacob.wav"
' *** read the notes for the song
for i=0 to 3 ! read song$(i) ! next i
data "c4","d","e","c"
' *** generate the first note
sine_signal(N,sig,100,2*hertz(song$(0))/nd,0,0,"0")
' *** encapsulate in a new .WAV file
wav_file(N,sig,1,4000,8,f$)
' *** generate the other notes and append them to the existing file
for i=1 to 3
sine_signal(N,sig,100,2*hertz(song$(i))/nd,0,0,"0")
wav_add_stream(f$,N,sig,255)
next i
' *** play it
play_music(f$)
' *** add another tone to the file and play it again
block_signal(N,sig,100,hertz("F#5")/nd,0,0,"0")
wav_add_stream(f$,N,sig,255)
pause .5 ! play_music(f$)
next t
' *** show header info
wav_info(f$,100,100,300,500,.7,.7,.7,1)
end
' 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 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
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
def play_it(mus$)
music m$ load mus$
ml=music_length(m$)
music m$ play
pause ml
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
{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$)
The only thing that gets me down is gravity...
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Saving a wave pattern to a .WAV file
Hi Richard,
Here is the scheme for correctly calculate the different parameters for a given note, note length, and sample rate for the wav file.
I also noticed that the term "frequency" was incorrectly used in the signal generating functions like sine_signal(). It merely is the number of cycles (one cycle beiing one complete sine wave), generated in the N output samples. But this is only the tone frequency if N equals the sample rate in the .WAV file.
In the wave generating functions, the term 'frequency' will be replaced by "cycle' related terms.
Playing withe the sample rate and the note duration in the testset hereafter will no longer affect the tone frequency produced by the speaker.
Here is the scheme for correctly calculate the different parameters for a given note, note length, and sample rate for the wav file.
I also noticed that the term "frequency" was incorrectly used in the signal generating functions like sine_signal(). It merely is the number of cycles (one cycle beiing one complete sine wave), generated in the N output samples. But this is only the tone frequency if N equals the sample rate in the .WAV file.
In the wave generating functions, the term 'frequency' will be replaced by "cycle' related terms.
Playing withe the sample rate and the note duration in the testset hereafter will no longer affect the tone frequency produced by the speaker.
Code: Select all
' INPUT DATA
S=4000 ' sample rate for .WAV file
T=0.5 ' duration of tone in seconds
F=440 ' frequency of tone
' CALCULATED DATA
N=T*S ' number of samples (bytes if mono) in data chunk
C=T*F ' # of cycles for function sine_wave()
dim sig(N) ! pi=4*atan(1)
f$="test.wav"
sine_signal(N,sig,100,C,0,0,"0")
wav_file(N,sig,1,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(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
def play_it(mus$)
music m$ load mus$
ml=music_length(m$)
music m$ play
pause ml
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
{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$)
- 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:
- Contact:
Re: Saving a wave pattern to a .WAV file
Nice improvement, with pitch and duration now independent. If that feature is integrated with your note-reading code, it should be possible to duplicate any melody.
The only thing that gets me down is gravity...
-
- Posts: 814
- Joined: Tue Apr 09, 2013 12:23 pm
- My devices: iPhone,iPad
Windows - Location: Groningen, Netherlands
- Flag:
Re: Saving a wave pattern to a .WAV file
We are not done with the basics yet. Chords are not possible yet (multichannel and multichunk .wav files are not available yet.
I had the impression that you will take care of the "upper layer" melody code, that you (or rather mr. K.) have designed. That's why i mentioned our Datamine project in an earlier post.
I am more interested at things like echo, filters, etc.
I had the impression that you will take care of the "upper layer" melody code, that you (or rather mr. K.) have designed. That's why i mentioned our Datamine project in an earlier post.
I am more interested at things like echo, filters, etc.
- 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:
- Contact:
Re: Saving a wave pattern to a .WAV file
Thanks, Henk. I will work on the melody aspect, but I prefer to wait until you are satisfied with the basics.
The only thing that gets me down is gravity...