-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoctoaudio.py
164 lines (138 loc) · 5.1 KB
/
octoaudio.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import os
import time
import threading
import alsaaudio
import wave
from octofiles import OctoFile
class OctoAudio():
def __init__(self, settings):
self.settings = settings
# Set parameters
self.periodsize = self.settings.get_buffersize()
self.devicename = self.settings.get_audiodevice()
self.filepath = False
self.preloaded = False
self.wav = False
self.device = False
if self.settings.get_verbose():
self.__list_cards()
def __list_cards(self):
print("Available Sound Cards:")
for i in alsaaudio.card_indexes():
(name, longname) = alsaaudio.card_name(i)
print(" {:d}: {} ({})".format(i, name, longname))
print("Available Audio Devices:")
devs = alsaaudio.pcms()
for i in range(len(devs)):
print(" {:d}: {}".format(i, devs[i]))
print("Desired Audio Device: {}\n".format(self.devicename))
def __setup_device(self, channels, framerate, format):
# pyalsaaudio 0.9-0.10
try:
device = alsaaudio.PCM(
type=alsaaudio.PCM_PLAYBACK,
mode=alsaaudio.PCM_NONBLOCK,
rate=framerate,
channels=channels,
format=format,
periodsize=self.periodsize,
device=self.devicename
)
except Exception as e:
# pyalsaaudio 0.8
try:
device = alsaaudio.PCM(
type=alsaaudio.PCM_PLAYBACK,
mode=alsaaudio.PCM_NONBLOCK,
device=self.devicename
)
device.setchannels(channels)
device.setrate(framerate)
device.setformat(format)
device.setperiodsize(self.periodsize)
except Exception as ee:
if self.settings.get_verbose():
print("Unable to initialize sound card.")
print(repr(ee))
return False
if self.settings.get_verbose():
print("Selected Sound Card: {}\n".format(device.cardname()))
return device
def stop(self):
if self.wav and not self.preloaded:
self.wav.close()
self.wav = False
self.device = False
def load(self, filepath):
self.stop()
if isinstance(filepath, OctoFile):
if not filepath.has_wave():
return False
self.filepath = os.path.abspath(filepath.wavepath)
if filepath.is_wave_loaded():
self.wav = filepath.wavefile
self.wav.rewind()
self.preloaded = True
if self.settings.get_verbose():
print("Using preloaded wave data.")
else:
self.preloaded = False
else:
self.filepath = os.path.abspath(filepath)
self.preloaded = False
if not self.wav:
try:
self.wav = wave.open(self.filepath, 'rb')
except Exception as e:
if self.settings.get_verbose():
print('Unable to open wave file: {}.'.format(self.filepath))
print(repr(e))
self.filepath = False
self.wav = False
return False
format = None
if self.wav.getsampwidth() == 1:
format = alsaaudio.PCM_FORMAT_U8
elif self.wav.getsampwidth() == 2:
format = alsaaudio.PCM_FORMAT_S16_LE
elif self.wav.getsampwidth() == 3:
format = alsaaudio.PCM_FORMAT_S24_3LE
elif self.wav.getsampwidth() == 4:
format = alsaaudio.PCM_FORMAT_S32_LE
else:
if self.settings.get_verbose():
print('Unsupported wave file format: {}.'.format(self.wav.getsampwidth()))
self.wav = False
return False
if self.settings.get_verbose():
print("Wave File Parameters:")
print(" Channels = {:d}".format(self.wav.getnchannels()))
print(" Sample Rate = {:d}".format(self.wav.getframerate()))
print(" Format = {}".format(format))
print(" Buffer Size = {}".format(self.periodsize))
self.device = self.__setup_device(self.wav.getnchannels(), self.wav.getframerate(), format)
if not self.device:
self.wav = False
self.device = False
return False
return True
def is_loaded(self):
return self.wav
def get_duration(self):
if not self.is_loaded():
return False
return self.wav.getnframes() / float(self.wav.getframerate())
def get_period_duration(self):
if not self.is_loaded():
return 0
return self.periodsize / float(self.wav.getframerate())
def write_buffer(self):
if not self.wav or not self.device:
return False
data = self.wav.readframes(self.periodsize)
if not data:
return False
self.device.write(data)
return True
def close(self):
self.stop()