forked from antiface/python-dsp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudiofile.py
executable file
·92 lines (77 loc) · 3.26 KB
/
audiofile.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
#!/usr/bin/python
# audiofile.py: Container class for an audio file
import wave
import struct
class AudioFile:
"""
Container class for an audio file. This class allows
for reading and writing wave files with translation of
packed data into unpacked data for manipulation by other
programs.
Mostly this acts as a proxy for the wave module. But this
class also abstracts packing/unpacking data away from clients.
"""
def __init__(self,filename,mode):
"""Creates a new AudioFile instance with the given filename.
Mode should be one of 'r' (read) or 'w' (write)."""
self.file_handle = wave.open(filename,mode)
if mode == 'w':
channels = 1
sample_width = 2
frame_rate = 44100
self.setparams(channels,
sample_width,
frame_rate,
0,
'NONE',
'not compressed')
def close(self):
"""Close the underlying file represented by this instance."""
self.file_handle.close()
def write(self,sample):
"""Write a sample to the underlying file.
The sample is checked to ensure it fits in the
size of the word the file expects."""
sample = self.check_clip(sample)
packed_out_data = struct.pack('h', sample)
self.file_handle.writeframes(packed_out_data)
def check_clip(self,sample):
"""Clip samples that are larger than the word size
the underlying file supports. Right now this is
hardcoded to 16 bit signed word size."""
if sample > 32767:
sample = 32767
if sample < -32768:
sample = -32768
return sample
def getnframes(self):
"""Return the number of frames in the underlying file."""
return self.file_handle.getnframes()
def getnchannels(self):
"""Return the number of channels in the underlying file."""
return self.file_handle.getnchannels()
def getframerate(self):
"""Return the framerate of the udnerlying file."""
return self.file_handle.getframerate()
def getsampwidth(self):
"""Return the sample width of the udnerlying file."""
return self.file_handle.getsampwidth()
def setparams(self,nchannels,sampwidth,framerate,nframes,comptype,compname):
"""Sets parameters in the wave file header."""
self.file_handle.setparams((nchannels,
sampwidth,
framerate,
nframes,
comptype,
compname))
def tell(self):
"""Return the current read position in the underlying file."""
return self.file_handle.tell()
def read(self, num_samples):
"""Read a number of samples from the underlying file.
This returns a tuple containing the requested number of
samples. For multichannel files the tuple will alternate
between each channel."""
frame = self.file_handle.readframes(num_samples)
frame_data = struct.unpack('%dh'%(self.getnchannels()), frame)
return frame_data