|
|
@@ -30,6 +30,41 @@ class callback: |
|
|
|
print('.') |
|
|
|
return 1 |
|
|
|
|
|
|
|
try: |
|
|
|
# if we have numpy, replace the above class |
|
|
|
import numpy as np |
|
|
|
class callback: |
|
|
|
def __init__(self, gen): |
|
|
|
print('Using Numpy.') |
|
|
|
self.freq = 440. |
|
|
|
t = np.arange(256, dtype=np.float32) / 48000.0 |
|
|
|
self.phase = 2*np.pi*t |
|
|
|
self.inc = 2*np.pi*256/48000 |
|
|
|
self.k = 0 |
|
|
|
def __call__(self, playback, capture): |
|
|
|
# Calculate sinusoid using numpy vector operation, as |
|
|
|
# opposed to per-sample computations in the generator |
|
|
|
# above that must be collected and packed one at a time. |
|
|
|
self.k += 256 |
|
|
|
if self.k > 48000: |
|
|
|
self.freq *= 2**(1/12.) |
|
|
|
self.k = 0 |
|
|
|
self.phase += self.inc |
|
|
|
samples = 0.5*np.cos(self.phase * self.freq) |
|
|
|
|
|
|
|
# Ensure result is the right size! |
|
|
|
assert samples.shape[0] == 256 |
|
|
|
assert samples.dtype == np.float32 |
|
|
|
|
|
|
|
# Use numpy array view to do a once-copy into memoryview |
|
|
|
# (ie. we only do a single byte-wise copy of the final |
|
|
|
# result into 'playback') |
|
|
|
usamples = samples.view(dtype=np.uint8) |
|
|
|
playback_array = np.array(playback, copy=False) |
|
|
|
np.copyto(playback_array, usamples) |
|
|
|
except ModuleNotFoundError: |
|
|
|
print('Numpy not available, using struct.') |
|
|
|
|
|
|
|
dac = rt.RtAudio() |
|
|
|
|
|
|
|
n = dac.getDeviceCount() |
|
|
|