Beispiel #1
0
class FMOperator(Oscillator):
	"""A class to represent an FM operator"""

	def __init__(
		self, freq=440.0, level=1.0, phase=0.0, feedback=0, wave_type='sine', 
		fm_type='DX', gate=Gate([0.0]), key_in=None
	):
		Oscillator.__init__(self, key_in)

		self.freq = freq				#frequency

		self.mixer = Mixer()			#mixer to add modulators' outputs

		#sound generator
		if fm_type == 'LinearFM':			
			self.generator = LinearFMGenerator(
				freq, level, phase, wave_type, self.mixer, key_in
			)
		elif fm_type == 'DX':
			self.generator = DXGenerator(
				freq, level, phase, wave_type, self.mixer, key_in
			)

		self.eg = ADSR(input=gate)		#envelope generator

		#amplifier
		self.amp = Amplifier(input=self.generator, mod=self.eg)

	def add_modulator(self, mod, level=1.0):
		"""Adds a modulator"""
		self.mixer.add_input(mod, level)

	def set_key_in(self, key_in):
		"""Sets key input"""
		self.key_in = key_in
		self.generator.set_key_in(key_in)

	def set_eg_params(self, *args, **kwargs):
		"""Sets parameters of the envelope"""
		self.eg.set_params(*args, **kwargs)

	def set_gate(self, gate):
		"""Sets the gate input"""
		self.eg.set_input(gate)

	def set_keyboard(self, keyboard):
		"""sets key and gate input from a keybord"""
		self.set_key_in(keyboard.key)
		self.set_gate(keyboard.gate)

	def output(self, t, **kwargs):
		"""Returns the value of operators signal in time t"""
		return self.amp.output(t, **kwargs)

	def draw(self, ax, time=None, cycles=1, **kwargs):
		"""
		Draws the shape of the operators output signal along with its 
		modulators and modulators' modulators etc.
		
		If 'time' is not provided, the shape will be drawn for 'cycles' cycles 
		of operators carrier generator
		"""

		#draw the operators output signal
		Oscillator.draw(self, ax, time, cycles, **kwargs)

		#draw modulators' output signals

		if time is None:
			time = cycles / np.float64(self.freq)

		try:
			kwargs['alpha'] *= 0.5
		except KeyError:
			kwargs['alpha'] = 0.5

		self.mixer.draw(ax, time, **kwargs)
op4.set_eg_params(0.0, 0.11, 0.0, 0.05)
op5.set_eg_params(0.0, 0.7, 0.2, 0.2)
op6.set_eg_params(0.0, 0.7, 0.2, 0.4)


#add keyboard
kbd = MonoKeyboard()

ops = [op1, op2, op3, op4, op5, op6]
for op in ops:
	op.set_keyboard(kbd)

#read a midi file
kbd.read_midi('midi\\dangerzonebass.mid')

#draw envelopes, keyboard outputs and the wave shape
fig, (ax1, ax2, ax3) = plt.subplots(3, 1)

for op in ops:
	op.eg.draw(ax2, 13, density=2000, alpha=0.5)

kbd.gate.draw(ax2, 13, density=20000, alpha=0.5)
kbd.key.draw(ax3, 13, density=2000)

mixer.draw(ax1, 1.0 / 110, density=1000)

#play the sound
mixer.play(13)

#show the outputs
plt.show()