from wavetable.utils import normalize, trim # Render a single sawtooth waveform generated by the StandardOscillator. s = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 1.0).render(s) wavfile.write('sounds/single.wav', 44100, s) # Render a detuned pair generated by StandardOscillator. sdp = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 0.5).render(sdp) StandardOscillator(43.65, 3.0, 0.5).render(sdp) wavfile.write('sounds/standard_detuned_pair.wav', 44100, sdp) # Now a detuned pair using the ResamplingOscillator. rdp = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 0.5).render(rdp) ResamplingOscillator(43.65, 3.0, 0.5).render(rdp) wavfile.write('sounds/resampling_detuned_pair.wav', 44100, rdp) # Next, to isolate the phase artifacts introduced by using the resampling # approach, we'll render the difference between the two previous approaches. wavfile.write('sounds/standard_resampling_diff.wav', 44100, normalize(trim(rdp - sdp, pow(2, 3 / 1200.0)))) # And to show that the RealTimeResamplingOscillator produces the same sound # as the classic ResamplingOscillator, we'll render another detuned pair here. rtdp = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 0.5).render(rtdp) RealTimeResamplingOscillator(43.65, 3.0, 0.5).render(rtdp) wavfile.write('sounds/realtime_detuned_pair.wav', 44100, rtdp)
plt.show() # Next, we'll show the difference in the waveform produced by using resampling # to apply detune when played next to a similar waveform vs. what I assume is # the standard method of applying detune, as described in the oscillators file. _x = np.linspace(0, 44100 * 4, 44100 * 4) ss = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 0.5).render(ss) StandardOscillator(43.65, 3.0, 0.5).render(ss) rs = np.zeros(44100 * 4, dtype='d') StandardOscillator(43.65, 0.0, 0.5).render(rs) ResamplingOscillator(43.65, 3.0, 0.5).render(rs) plt.plot(_x, normalize(trim(rs - ss, pow(2, 3 / 1200.0)))) plt.show() # Now, to show that we can introduce the same artifacts in real time, we'll # show that the output of the ResamplingOscillator and the # RealTimeResamplingOscillator are actually the same. rs = np.zeros(44100 * 4, dtype='d') ResamplingOscillator(43.65, 3.0, 1.0).render(rs) rt = np.zeros(44100 * 4, dtype='d') RealTimeResamplingOscillator(43.65, 3.0, 1.0).render(rt) trim(rt, pow(2, 3 / 1200.0)) assert np.allclose(rs, rt) plt.plot(_x, rs - rt) plt.show()