'''
Final project for chaos, creating a ring buffer using simulated speakers
'''
# import in a try-except statement in case a module is not installed
try:	
	import numpy as np
	import pylab as pyl
	from scikits.audiolab import Format, Sndfile

except ImportError, msg:	# catch any import exceptions, print error message
	print 'Error importing modules:', msg

class Speaker():
	
	#This will be a speaker feedback loop with time delays, and the option
	#to apply a range of different types of functions to the signal
	
	
	def __init__(self):
		#Initializes base parameters for the speaker
		self.r_default = 1.3
		self.time_delay_default =10000
		self.time_delay = 10000
		self.r = .2
		#A string description of the speaker
		self.description = 'Time delayed speaker'
	
	def setr(self,r):
	#sets r
		self.r = r
	
	def settime_delay(self, time):
	#Sets the time delay
		self.time_delay = time
	
	def reset(self):
		#resets the values to default
		self.r = self.r_default
		self.time_delay = self.time_delay_default
		self.time_elapsed = self.time_elapsed_default
	
	def current(self):
	#Tells the current values of the system
		print "Current r:", self.r
		print "Current time delay:", self.time_delay
	
	def current_time_delay(self):
	#returns current time delay
		return self.time_delay
	
	def time_elapsed(self):
	#Returns time_elapsed
		return time_elapsed
	
	def time_delay(self):
	#Returns time delayed
		return self.time_delay
	
	def __repr__(self):
	#Returns the description of the object
		return self.description
	
	def func(self, lst, t):
	#Defines the actual math operator for the logistic equation f(x) = r*x*(1-x)
		return self.r * lst[t]
	
	def on_off(self, func, control):
	#Defines a term that will return a function if the second term is greater than zero
		if control < 0:
			return lambda lst, t: 0
		else:
			return func
	
	def output(self, lst, current_time):
	#The actual delayed signal that will be produced
		return self.on_off(self.func, current_time - self.time_delay)(lst, current_time-self.time_delay)
		



	#Defining a logistic class of speaker
class logistic(Speaker):
	def __init__(self):
	#Defines one of the speaker functions, a logistic operator f(x) = r*x*(1-x)
		Speaker.__init__(self)
		self.description = 'Time delayed speaker with a logistic amplifier'
	
	def func(self, lst, t):
	#Defines the actual math operator for the logistic equation f(x) = r*x*(1-x)
		return self.r * lst[t] * (1.0 - lst[t])

#Defining a linear class of speaker
class linear(Speaker):
	def __init__(self):
	#Defines one of the speaker functions, a logistic operator f(x) = r*x
		Speaker.__init__(self)
		self.description = 'Time delayed speaker with a linear amplifier'
	
	def func(self, lst, t):
	#Defines the actual math operator for the logistic equation f(x) = r*x*(1-x)
		return self.r * lst[t]

#defines a function for a speaker being off, regardless of input the output is zero
class off_switch(Speaker):
		def __init__(self):
		#Defines one of the speaker functions as off
			Speaker.__init__(self)
			self.description = 'Time delayed speaker with a linear amplifier'
	
		def func(self, lst, t):
		#Defines the actual math operator for the logistic equation f(x) = r*x*(1-x)
			return 0

'''
pyl.plot(gt)
pyl.xlabel('time')
pyl.ylabel('Microphone signal')
pyl.show()

filename = 'wave output.wav'
wave_output(self, gt, filename, Signal_sample_rate)

print 'File produced'

'''