diff --git a/blend.ogg b/blend.ogg index fde4e1b..6158fbd 100644 Binary files a/blend.ogg and b/blend.ogg differ diff --git a/blend.py b/blend.py index b1c9df8..19e45f5 100644 --- a/blend.py +++ b/blend.py @@ -250,11 +250,11 @@ yue.process(melody, 24, 4, blend=1) yue.process(bass, 24, gain=1.5, blend=1) yue.process(bass, 32, gain=1.5, blend=1) yue.process(melody, 40, 4, blend=1) -yue.process(melody2, 40, 4, blend=1) +yue.process(melody2, 40, 4, blend=1, waveform=yue.seething) yue.process(bass, 40, gain=1.5, blend=1) yue.process(bass, 48, gain=1.5, blend=1) yue.process(melody, 56, 4, blend=1) -yue.process(melody3, 56, 4, blend=1) +yue.process(melody3, 56, 4, blend=1, waveform=yue.seething) yue.process(bass, 56, gain=1.5, blend=1) yue.process(bass, 64, gain=1.5, blend=1) yue.process(outro, 72, 4, blend=1) diff --git a/yue.py b/yue.py index dda9e79..1cb3885 100644 --- a/yue.py +++ b/yue.py @@ -8,21 +8,6 @@ bitrate = 44100 music = [] -def process(notes, start, speed=1, gain=1, blend=0): - """ - Adds a list of notes to the music list - """ - t = start - for note in notes: - vol = 1 - if len(note) == 4: - vol = note[3] - start = min(t, t + note[0] / speed) - end = max(t, t + note[0] / speed) - music.append((start, end + 16 * int(blend), note[1], note[2], vol * gain)) - t = end - - def freq(octave, step): """ Returns the frequency of a note @@ -30,9 +15,9 @@ def freq(octave, step): return 55 * 2 ** (octave + step / 12 - 1) -def tone(f, t): +def droplet(f, t): """ - Returns the intensity of a tone of frequency f sampled at time t + Returns the intensity of the "droplet" waveform of frequency f sampled at time t https://dsp.stackexchange.com/questions/46598/mathematical-equation-for-the-sound-wave-that-a-piano-makes https://youtu.be/ogFAHvYatWs?t=254 """ @@ -45,6 +30,21 @@ def tone(f, t): return Y +def seething(f, t): + """ + Returns the intensity of the "seething" waveform of frequency f sampled at time t + """ + w = 2 * math.pi * f + Y = 0.6 * math.sin(w * t) * math.exp(-0.0005 * w * t) + Y += 0.1 * math.sin(0.99 * w * t) * math.exp(-0.0005 * w * t) + Y += 0.1 * math.sin(1.01 * w * t) * math.exp(-0.0005 * w * t) + Y += 0.2 * math.sin(2 * w * t) * math.exp(-0.0005 * w * t) + Y += math.copysign(Y * Y, Y) + Y *= 1 + 16 * t * math.exp(-6 * t) + Y *= 0.5 * min(24 * t, 1) + return Y + + def at(t): """ Returns the total intensity of music sampled at time t @@ -56,10 +56,25 @@ def at(t): for j in range(max(i - 32, 0), i): m = music[j] if m[1] > t: - ret += m[4] * tone(freq(m[2], m[3]), t - m[0]) + ret += m[4] * m[5](freq(m[2], m[3]), t - m[0]) return int(2**28 * ret) +def process(notes, start, speed=1, gain=1, blend=0, waveform=droplet): + """ + Adds a list of notes to the music list + """ + t = start + for note in notes: + vol = 1 + if len(note) == 4: + vol = note[3] + start = min(t, t + note[0] / speed) + end = max(t, t + note[0] / speed) + music.append((start, end + 16 * int(blend), note[1], note[2], vol * gain, waveform)) + t = end + + def play(start, end): """ Print music from the start time to end time encoded in s32 to standard output