You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

107 lines
2.9KB

  1. from __future__ import print_function
  2. import threading
  3. import rtaudio as rt
  4. from math import cos
  5. import struct
  6. class audio_generator:
  7. def __init__(self):
  8. self.idx = -1
  9. self.freq = 440.
  10. def __call__(self):
  11. self.idx += 1
  12. if self.idx%48000 == 0:
  13. self.freq *= 2**(1/12.)
  14. return 0.5*cos(2.*3.1416*self.freq*self.idx/48000.)
  15. class callback:
  16. def __init__(self, gen):
  17. self.gen = gen
  18. self.i = 0
  19. def __call__(self,playback, capture):
  20. [struct.pack_into("f", playback, 4*o, self.gen()) for o in range(256)]
  21. self.i = self.i + 256
  22. if self.i > 48000*10:
  23. print('.')
  24. return 1
  25. try:
  26. # if we have numpy, replace the above class
  27. import numpy as np
  28. class callback:
  29. def __init__(self, gen):
  30. print('Using Numpy.')
  31. self.freq = 440.
  32. t = np.arange(256, dtype=np.float32) / 48000.0
  33. self.phase = 2*np.pi*t
  34. self.inc = 2*np.pi*256/48000
  35. self.k = 0
  36. def __call__(self, playback, capture):
  37. # Calculate sinusoid using numpy vector operation, as
  38. # opposed to per-sample computations in the generator
  39. # above that must be collected and packed one at a time.
  40. self.k += 256
  41. if self.k > 48000:
  42. self.freq *= 2**(1/12.)
  43. self.k = 0
  44. self.phase += self.inc
  45. samples = 0.5*np.cos(self.phase * self.freq)
  46. # Ensure result is the right size!
  47. assert samples.shape[0] == 256
  48. assert samples.dtype == np.float32
  49. # Use numpy array view to do a once-copy into memoryview
  50. # (ie. we only do a single byte-wise copy of the final
  51. # result into 'playback')
  52. usamples = samples.view(dtype=np.uint8)
  53. playback_array = np.array(playback, copy=False)
  54. np.copyto(playback_array, usamples)
  55. except ModuleNotFoundError:
  56. print('Numpy not available, using struct.')
  57. dac = rt.RtAudio()
  58. n = dac.getDeviceCount()
  59. print('Number of devices available: ', n)
  60. for i in range(n):
  61. try:
  62. print(dac.getDeviceInfo(i))
  63. except rt.RtError as e:
  64. print(e)
  65. print('Default output device: ', dac.getDefaultOutputDevice())
  66. print('Default input device: ', dac.getDefaultInputDevice())
  67. print('is stream open: ', dac.isStreamOpen())
  68. print('is stream running: ', dac.isStreamRunning())
  69. oParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}
  70. iParams = {'deviceId': 0, 'nChannels': 1, 'firstChannel': 0}
  71. try:
  72. dac.openStream(oParams,oParams,48000,256,callback(audio_generator()) )
  73. except rt.RtError as e:
  74. print(e)
  75. else:
  76. dac.startStream()
  77. import time
  78. print('latency: ', dac.getStreamLatency())
  79. while (dac.isStreamRunning()):
  80. time.sleep(0.1)
  81. print(dac.getStreamTime())
  82. dac.stopStream()
  83. dac.abortStream()
  84. dac.closeStream()