Thanks for the information Stefano. I have solved the problem of clicks and pops by the used of overlapping voices.
My latest code is now available on GitHub at
https://github.com/RayCannon/Toccata which now contains the the code to produce the full Toccata from Bach's Toccata and Fugue in D-minor.
Since WAV files are huge, (Toccata.wav is 36Mb) the GitHub has an MP3 version (produced from the WAV version) at only 2Mb.
Within the code, I have augmented the simple sine waves with multiple harmonics with varying loudness levels. These harmonics attempt to simulate various organ pipes characteristics, such as "Closed pipes" having mainly odd harmonic numbers unlike "Open pipes" having both odd and even. In some pipes, the fundamental is not the loudest harmonic, which greatly surprised me!
Code: Select all
(harmonics volumes)←loud SelectPipe pipe;Hnums;ratios;powers
⍝ set up the harmonics for any "set of pipes"
⍝ See http://www.colinpykett.org.uk/observations-on-organ-pipe-sounds-frequency-spectra.htm#Refs
:Select pipe
:Case 'Q' ⍝ Silence
harmonics←,1
volumes←,loud
:Case 'D' ⍝ Open Diapason both odd and even harmonics
ratios←1 4 8 8 8 8 10 32 64
harmonics←1+⍳≢ratios
powers←2×harmonics
volumes←loud÷powers{⍵,(≢⍵)↓⍺}ratios
:Case 'F' ⍝ closed Flute mainly odd numbered harmonics
ratios←1 8 2 16 8 32
harmonics←1+⍳≢ratios
powers←2×harmonics
volumes←loud÷powers{⍵,(≢⍵)↓⍺}ratios
:Case 'R' ⍝ Reed pipe
ratios←1.5 1.6 1 2.2 2.5 3 6 12 24 48
harmonics←1+⍳≢ratios
powers←2×harmonics
volumes←loud÷powers{⍵,(≢⍵)↓⍺}ratios
:Case 'S' ⍝ open String Pipe
ratios←(3⍴1.5),1,(⌽2+2÷1+⍳6),(8+4×⍳8)
harmonics←1+⍳≢ratios
powers←2×harmonics
volumes←loud÷powers{⍵,(≢⍵)↓⍺}ratios
:Else
ratios←1+⍳11
harmonics←1+⍳≢ratios
powers←2×harmonics
volumes←loud÷powers{⍵,(≢⍵)↓⍺}ratios
:End
The values returned by "SelectPipe" are <harmonics> and <volumes>.
<harmonics> is multiplied with the fundamental frequency to produce the frequency of all the harmonics being produced. The resulting samples values are then multiplied by the <volumes> to adjust the relative loudness of each harmonic.
In addition to the harmonics, I have added reverberation, to attempt to simulate a large hall. (60db drop after 2 seconds.)
Code: Select all
Echo;a;i;⎕IO;delay;j;echo;delayecho
⍝ aim for 2 seconds for reverb to drop by 60db
⎕IO←1
j←2
:For i :In 2↓2*⍳8 ⍝ 6 steps each of 10 db loss
echo←G.(left+right)÷i ⍝ an echo is in mono but reduced in amplituide
j+←1 ⍝ shorten the delay each time round the loop seems to help
delay←-⌊G.rate÷j ⍝ initial delay 1/3 of a second
delayecho←delay⌽echo ⍝ add a delay
G.left+←delayecho ⍝ add the echo to the initial sound
G.right+←delayecho ⍝ to both channels
:End
Note that the original left and right channels end in extensive silence, so the delay is produced by rotation of some of this silence from the end to the start.
I have attempted to add the MP3 file to this reply, but the forum limits file sizes:
"The file is too big, maximum allowed size is 256 KiB."