Skip to content

Commit

Permalink
Change oscillator waveform func based on sfx note instrument
Browse files Browse the repository at this point in the history
  • Loading branch information
elgopher committed Sep 2, 2023
1 parent d0dcf63 commit ea59173
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
2 changes: 1 addition & 1 deletion audio/synth.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (s *Synthesizer) ReadSamples(buffer []float64) {
if ch.noteNo == len(sfx.Notes) {
ch.playing = false
} else {
//ch.oscillator.Func = oscillatorFunc(sfx.Notes[ch.noteNo].Instrument)
ch.oscillator.Func = oscillatorFunc(sfx.Notes[ch.noteNo].Instrument)
ch.oscillator.FreqHz = pitchToFreq(sfx.Notes[ch.noteNo].Pitch)
}
}
Expand Down
52 changes: 52 additions & 0 deletions audio/synth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,26 @@ func TestSynthesizer_Sfx(t *testing.T) {
// then
assert.True(t, dominantFrequency(buffer1) < dominantFrequency(buffer2), "frequency of pitch C1 must be smaller than D#5")
})

t.Run("should generate different wave when second note has a different instrument", func(t *testing.T) {
e := audio.SoundEffect{
Notes: [32]audio.Note{
{Instrument: audio.InstrumentTriangle, Volume: audio.VolumeLoudest},
{Instrument: audio.InstrumentSaw, Volume: audio.VolumeLoudest},
},
Speed: 32,
}
synth := audio.Synthesizer{}
synth.SetSfx(0, e)
synth.Sfx(0, 0, 0, 31)
buffer1 := make([]float64, 32*durationOfNoteWhenSpeedIsOne)
synth.ReadSamples(buffer1)
buffer2 := make([]float64, 32*durationOfNoteWhenSpeedIsOne)
// when
synth.ReadSamples(buffer2)
// then
assertDifferentShape(t, buffer1, buffer2)
})
}

func clone(s []byte) []byte {
Expand Down Expand Up @@ -562,3 +582,35 @@ func hfft(input []float64, freqs []complex128, n, step int) {
freqs[k], freqs[k+h] = freqs[k]+e, freqs[k]-e
}
}

func assertDifferentShape(t *testing.T, buffer1, buffer2 []float64) {
dtw := dtwDistance(buffer1, buffer2)
assert.Truef(t, dtw >= 30.00, "Waves should have different shape, but dtw distance = %f. Must be >= 30.00", dtw)
}

// dtwDistance calculates dynamic time warping distance between two signals
func dtwDistance(signal1, signal2 []float64) float64 {
len1, len2 := len(signal1), len(signal2)
dtw := make([][]float64, len1+1)
for i := range dtw {
dtw[i] = make([]float64, len2+1)
}

for i := 1; i <= len1; i++ {
for j := 1; j <= len2; j++ {
cost := math.Abs(signal1[i-1] - signal2[j-1])
dtw[i][j] = cost + min3(dtw[i-1][j], dtw[i][j-1], dtw[i-1][j-1])
}
}

return dtw[len1][len2]
}

func min3(a, b, c float64) float64 {
if a <= b && a <= c {
return a
} else if b <= a && b <= c {
return b
}
return c
}

0 comments on commit ea59173

Please sign in to comment.