@@ -55,9 +55,9 @@ class WaveBuilder:
5555 a member of the ``WaveShape`` class (type: string). The floating point
5656 oscillator frequency is defined as either a frequency in Hertz or
5757 overtone ratio based on the fundamental (lowest) frequency. The
58- amplitude is a floating point value between 0 .0 and 1.0 (inclusive).
59- Amplitude values outside the range will produce overflow effects
60- that may be unwanted . No default.
58+ amplitude is a floating point value between -1 .0 and 1.0 (inclusive).
59+ Amplitude values less than zero will flip the phase of the resultant
60+ oscillator waveform 180 degrees . No default.
6161 :param integer table_length: The number of samples contained in the
6262 resultant waveform table. No default.
6363 :param integer sample_max: The maximum positive value of a sample,
@@ -86,7 +86,7 @@ def __init__(
8686 ):
8787 self ._oscillators = oscillators
8888 self ._table_length = table_length
89- self ._sample_max = sample_max
89+ self ._sample_max = int ( sample_max )
9090 self ._lambda_factor = lambda_factor
9191 self ._loop_smoothing = loop_smoothing
9292 self ._debug = debug
@@ -118,11 +118,11 @@ def table_length(self, new_table_length):
118118 def sample_max (self ):
119119 """The maximum positive value of a sample, limited to a signed
120120 16-bit integer value (0 to 32767)."""
121- return self ._sample_max
121+ return int ( self ._sample_max )
122122
123123 @sample_max .setter
124124 def sample_max (self , new_sample_max = 32767 ):
125- self ._sample_max = new_sample_max
125+ self ._sample_max = int ( new_sample_max )
126126 self ._update_table ()
127127
128128 @property
@@ -176,12 +176,12 @@ def summed_amplitude(self):
176176 # pylint: disable=unused-argument
177177 def _noise_wave (self , ratio , amplitude ):
178178 """Returns a sample array with a noise waveform adjusted to a specified amplitude."""
179+ amp_factor = abs (
180+ min (int (round (self ._sample_max * amplitude , 0 )), self ._sample_max )
181+ )
179182 _temporary = np .array (
180183 [
181- random .randint (
182- int (- self ._sample_max * amplitude ),
183- int (self ._sample_max * amplitude ),
184- )
184+ random .randint (- amp_factor , amp_factor )
185185 for _ in range (self ._table_length )
186186 ],
187187 dtype = np .int16 ,
@@ -191,6 +191,7 @@ def _noise_wave(self, ratio, amplitude):
191191 def _saw_wave (self , ratio , amplitude ):
192192 """Returns a waveform array with a saw wave waveform proportional
193193 to the frequency ratio and adjusted to a specified amplitude."""
194+ amp_factor = min (int (round (self ._sample_max * amplitude , 0 )), self ._sample_max )
194195 _temporary = np .array ([], dtype = np .int16 ) # Create a zero-length array
195196
196197 # Calculate the array length and subtract the initial zero element
@@ -203,13 +204,13 @@ def _saw_wave(self, ratio, amplitude):
203204 _temporary ,
204205 np .linspace (
205206 0 ,
206- int (self . _sample_max * amplitude ),
207+ int (amp_factor ),
207208 half_lambda - 1 ,
208209 dtype = np .int16 ,
209210 ),
210211 np .array ([0 ], dtype = np .int16 ),
211212 np .linspace (
212- int (- self . _sample_max * amplitude ),
213+ int (- amp_factor ),
213214 0 ,
214215 half_lambda - 1 ,
215216 dtype = np .int16 ,
@@ -224,6 +225,7 @@ def _saw_wave(self, ratio, amplitude):
224225 def _sine_wave (self , ratio , amplitude ):
225226 """Returns a waveform array with a sine wave waveform proportional
226227 to the frequency ratio and adjusted to a specified amplitude."""
228+ amp_factor = min (int (round (self ._sample_max * amplitude , 0 )), self ._sample_max )
227229 _temporary = np .array (
228230 np .sin (
229231 np .linspace (
@@ -233,15 +235,15 @@ def _sine_wave(self, ratio, amplitude):
233235 endpoint = False ,
234236 )
235237 )
236- * amplitude
237- * self ._sample_max ,
238+ * amp_factor ,
238239 dtype = np .int16 ,
239240 )
240241 return _temporary
241242
242243 def _square_wave (self , ratio , amplitude ):
243244 """Returns a waveform array with a square wave waveform proportional
244245 to the frequency ratio and adjusted to a specified amplitude."""
246+ amp_factor = min (int (round (self ._sample_max * amplitude , 0 )), self ._sample_max )
245247 # Create a zero-length temporary array
246248 _temporary = np .array ([], dtype = np .int16 )
247249
@@ -254,11 +256,9 @@ def _square_wave(self, ratio, amplitude):
254256 (
255257 _temporary ,
256258 np .array ([0 ], dtype = np .int16 ),
257- np .ones (half_lambda - 1 , dtype = np .int16 )
258- * int (self ._sample_max * amplitude ),
259+ np .ones (half_lambda - 1 , dtype = np .int16 ) * int (amp_factor ),
259260 np .array ([0 ], dtype = np .int16 ),
260- np .ones (half_lambda - 1 , dtype = np .int16 )
261- * int (- self ._sample_max * amplitude ),
261+ np .ones (half_lambda - 1 , dtype = np .int16 ) * int (- amp_factor ),
262262 )
263263 )
264264
@@ -269,14 +269,15 @@ def _square_wave(self, ratio, amplitude):
269269 def _triangle_wave (self , ratio , amplitude ):
270270 """Returns a waveform array with a triangle wave waveform proportional
271271 to the frequency ratio and adjusted to a specified amplitude."""
272+ amp_factor = min (int (round (self ._sample_max * amplitude , 0 )), self ._sample_max )
272273 # Create a zero-length temporary array
273274 _temporary = np .array ([], dtype = np .int16 )
274275
275276 # Calculate the sample length of one-quarter lambda
276277 quarter_lambda = int ((self ._table_length / (self ._lambda_factor * 4 )) / ratio )
277278
278279 # Calculate a one-step increment for even quarter-lambda segments
279- increment = int (self . _sample_max / quarter_lambda * amplitude )
280+ increment = int (amp_factor / quarter_lambda )
280281
281282 # Build the waveform array from a full-lambda waveform
282283 while len (_temporary ) < self ._table_length :
@@ -285,24 +286,24 @@ def _triangle_wave(self, ratio, amplitude):
285286 _temporary ,
286287 np .linspace (
287288 0 ,
288- int ( round ( self . _sample_max * amplitude , 0 )) ,
289+ amp_factor ,
289290 quarter_lambda ,
290291 dtype = np .int16 ,
291292 ),
292293 np .linspace (
293- int ( round ( self . _sample_max * amplitude , 0 )) - increment ,
294+ amp_factor - increment ,
294295 0 ,
295296 quarter_lambda ,
296297 dtype = np .int16 ,
297298 ),
298299 np .linspace (
299300 0 - increment ,
300- int ( round ( - self . _sample_max * amplitude , 0 )) ,
301+ - amp_factor ,
301302 quarter_lambda ,
302303 dtype = np .int16 ,
303304 ),
304305 np .linspace (
305- int ( round ( - self . _sample_max * amplitude , 0 )) + increment ,
306+ - amp_factor + increment ,
306307 0 - increment ,
307308 quarter_lambda ,
308309 dtype = np .int16 ,
@@ -322,7 +323,9 @@ def _update_table(self):
322323 (t , freq / fundamental_frequency , a ) for t , freq , a in self ._oscillators
323324 ]
324325
325- self ._summed_amplitude = sum ([osc [2 ] for osc in self ._oscillators ])
326+ self ._summed_amplitude = sum ([abs (osc [2 ]) for osc in self ._oscillators ])
327+ if self ._summed_amplitude > 1.0 :
328+ raise ValueError (f"Summed amplitude of oscillators exceeds 1.0." )
326329
327330 # Test each oscillator ratio to confirm that table_length has sufficient resolution
328331 for overtone in self ._oscillators :
0 commit comments