-
Notifications
You must be signed in to change notification settings - Fork 0
/
wav_read.py
134 lines (104 loc) · 3.77 KB
/
wav_read.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
"""
Created 12-26-17 by Matthew C. McCallum
"""
# Local modules
from .wav_fmt import *
from .audio_read import *
# Local submodules
# None.
# Thirdparty modules
import numpy as np
# Python library imports
import wave
import struct
class WavRead(AudioRead):
"""
A wave reader object for getting samples from file
"""
SAMPLE_FMT_NONE = 'None'
SAMPLE_FMT_INT_INTERLEAVED = 'Interleaved Integers'
SAMPLE_FMT_FLOAT_ARRAY = 'Float 2D Array'
def __init__( self, filehandle ):
"""
Constructor.
Args:
filehandle -> str or seekable file - A string or seekable file like object describing either the filename and
path of the audio wav file to be read, or a stream to the file data itself.
"""
self._file = filehandle
self._data = None
self._data_fmt = self.SAMPLE_FMT_NONE
with wave.open(self._file, 'rb') as audio:
self._num_frames = audio.getnframes()
self._fmt = WavFmt.FromWav( audio )
if type(self._file) is not str:
self._file.seek(0)
def ReadSamplesInterleavedInt( self ):
"""
Reads all samples from the wav file as integers in an interleaved list.
This replaces any previous data read from the wav file.
Return:
list(int) - A list of interleaved samples from the audio file.
"""
with wave.open( self._file, 'rb' ) as audio:
data = audio.readframes( self._num_frames )
if type(self._file) is not str:
self._file.seek(0)
data = struct.unpack( self._fmt.PackingString( self._num_frames ), data )
self._data_fmt = self.SAMPLE_FMT_INT_INTERLEAVED
self._data = list(data)
return self._data
def ReadSamplesFloat( self ):
"""
Reads all samples from the wav file as floats in the range -1.0 <= sample <= 1.0.
This replaces any previous data read from the wav file.
Return:
np.ndarray - An array of dimensions (num_channels, num_frames) containing float valued audio samples.
"""
self.ReadSamplesInterleavedInt()
return_array = np.zeros( ( self._fmt.n_channels, self._num_frames ) )
for channel in range( self._fmt.n_channels ):
return_array[channel,:] = np.array( self._data[channel::self._fmt.n_channels] )/( 2.0**self._fmt.bit_depth )
self._data_fmt = self.SAMPLE_FMT_FLOAT_ARRAY
self._data = return_array
return self._data
@property
def fmt( self ):
"""
Get the audio format object describing the file audio parameters, e.g., bit-depth, number channels, etc..
Return:
WavFmt - An object containing the audio format parameters.
"""
return self._fmt
@property
def data( self ):
"""
Any data that has been previously read in form the wave file.
Return:
? - Audio sample data in the format that was most recently read from file.
"""
return self._data
@property
def audio_length(self):
"""
The length of the audio in the file in seconds.
Return:
float - The duration of the audio file in seconds.
"""
return self._num_frames/self._fmt.samp_rate
@property
def data_fmt( self ):
"""
The current audio sample format of the data.
Return:
str - A string constant describing the format in which the class's data is in.
"""
return self._data_fmt
@property
def audio_length( self ):
"""
The length of the audio in the file in seconds.
Return:
float - The duration of the audio file in seconds.
"""
return self._num_frames/self._fmt.samp_rate