Skip to content

Commit dc51a11

Browse files
committed
Make audio/fifo pure
1 parent e3a0cbb commit dc51a11

File tree

1 file changed

+55
-43
lines changed

1 file changed

+55
-43
lines changed
Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from av.audio.frame cimport alloc_audio_frame
2-
from av.error cimport err_check
1+
import cython
2+
from cython.cimports.av.audio.frame import alloc_audio_frame
3+
from cython.cimports.av.error import err_check
34

45

5-
cdef class AudioFifo:
6+
@cython.cclass
7+
class AudioFifo:
68
"""A simple audio sample FIFO (First In First Out) buffer."""
79

810
def __repr__(self):
@@ -22,7 +24,8 @@ def __dealloc__(self):
2224
if self.ptr:
2325
lib.av_audio_fifo_free(self.ptr)
2426

25-
cpdef write(self, AudioFrame frame):
27+
@cython.ccall
28+
def write(self, frame: AudioFrame | None):
2629
"""write(frame)
2730
2831
Push a frame of samples into the queue.
@@ -45,7 +48,6 @@ def __dealloc__(self):
4548
return
4649

4750
if not self.ptr:
48-
4951
# Hold onto a copy of the attributes of the first frame to populate
5052
# output frames with.
5153
self.template = alloc_audio_frame()
@@ -60,44 +62,54 @@ def __dealloc__(self):
6062
self.pts_per_sample = 0
6163

6264
self.ptr = lib.av_audio_fifo_alloc(
63-
<lib.AVSampleFormat>frame.ptr.format,
65+
cython.cast(lib.AVSampleFormat, frame.ptr.format),
6466
frame.layout.nb_channels,
65-
frame.ptr.nb_samples * 2, # Just a default number of samples; it will adjust.
67+
frame.ptr.nb_samples
68+
* 2, # Just a default number of samples; it will adjust.
6669
)
6770

6871
if not self.ptr:
6972
raise RuntimeError("Could not allocate AVAudioFifo.")
7073

7174
# Make sure nothing changed.
7275
elif (
73-
frame.ptr.format != self.template.ptr.format or
74-
# TODO: frame.ptr.ch_layout != self.template.ptr.ch_layout or
75-
frame.ptr.sample_rate != self.template.ptr.sample_rate or
76-
(frame._time_base.num and self.template._time_base.num and (
77-
frame._time_base.num != self.template._time_base.num or
78-
frame._time_base.den != self.template._time_base.den
79-
))
76+
frame.ptr.format != self.template.ptr.format
77+
or frame.ptr.sample_rate != self.template.ptr.sample_rate
78+
or (
79+
frame._time_base.num
80+
and self.template._time_base.num
81+
and (
82+
frame._time_base.num != self.template._time_base.num
83+
or frame._time_base.den != self.template._time_base.den
84+
)
85+
)
8086
):
8187
raise ValueError("Frame does not match AudioFifo parameters.")
8288

8389
# Assert that the PTS are what we expect.
84-
cdef int64_t expected_pts
90+
expected_pts = cython.declare(int64_t)
8591
if self.pts_per_sample and frame.ptr.pts != lib.AV_NOPTS_VALUE:
86-
expected_pts = <int64_t>(self.pts_per_sample * self.samples_written)
92+
expected_pts = cython.cast(
93+
int64_t, self.pts_per_sample * self.samples_written
94+
)
8795
if frame.ptr.pts != expected_pts:
8896
raise ValueError(
89-
"Frame.pts (%d) != expected (%d); fix or set to None." % (frame.ptr.pts, expected_pts)
97+
"Frame.pts (%d) != expected (%d); fix or set to None."
98+
% (frame.ptr.pts, expected_pts)
9099
)
91100

92-
err_check(lib.av_audio_fifo_write(
93-
self.ptr,
94-
<void **>frame.ptr.extended_data,
95-
frame.ptr.nb_samples,
96-
))
101+
err_check(
102+
lib.av_audio_fifo_write(
103+
self.ptr,
104+
cython.cast(cython.pointer[cython.p_void], frame.ptr.extended_data),
105+
frame.ptr.nb_samples,
106+
)
107+
)
97108

98109
self.samples_written += frame.ptr.nb_samples
99110

100-
cpdef read(self, int samples=0, bint partial=False):
111+
@cython.ccall
112+
def read(self, samples: cython.int = 0, partial: cython.bint = False):
101113
"""read(samples=0, partial=False)
102114
103115
Read samples from the queue.
@@ -115,7 +127,7 @@ def __dealloc__(self):
115127
if not self.ptr:
116128
return
117129

118-
cdef int buffered_samples = lib.av_audio_fifo_size(self.ptr)
130+
buffered_samples: cython.int = lib.av_audio_fifo_size(self.ptr)
119131
if buffered_samples < 1:
120132
return
121133

@@ -127,31 +139,35 @@ def __dealloc__(self):
127139
else:
128140
return
129141

130-
cdef AudioFrame frame = alloc_audio_frame()
142+
frame: AudioFrame = alloc_audio_frame()
131143
frame._copy_internal_attributes(self.template)
132144
frame._init(
133-
<lib.AVSampleFormat>self.template.ptr.format,
134-
<lib.AVChannelLayout>self.template.ptr.ch_layout,
145+
cython.cast(lib.AVSampleFormat, self.template.ptr.format),
146+
cython.cast(lib.AVChannelLayout, self.template.ptr.ch_layout),
135147
samples,
136148
1, # Align?
137149
)
138150

139-
err_check(lib.av_audio_fifo_read(
140-
self.ptr,
141-
<void **>frame.ptr.extended_data,
142-
samples,
143-
))
151+
err_check(
152+
lib.av_audio_fifo_read(
153+
self.ptr,
154+
cython.cast(cython.pointer[cython.p_void], frame.ptr.extended_data),
155+
samples,
156+
)
157+
)
144158

145159
if self.pts_per_sample:
146-
frame.ptr.pts = <uint64_t>(self.pts_per_sample * self.samples_read)
160+
frame.ptr.pts = cython.cast(
161+
uint64_t, self.pts_per_sample * self.samples_read
162+
)
147163
else:
148164
frame.ptr.pts = lib.AV_NOPTS_VALUE
149165

150166
self.samples_read += samples
151-
152167
return frame
153168

154-
cpdef read_many(self, int samples, bint partial=False):
169+
@cython.ccall
170+
def read_many(self, samples: cython.int, partial: cython.bint = False):
155171
"""read_many(samples, partial=False)
156172
157173
Read as many frames as we can.
@@ -162,8 +178,8 @@ def __dealloc__(self):
162178
163179
"""
164180

165-
cdef AudioFrame frame
166-
frames = []
181+
frame: AudioFrame
182+
frames: list = []
167183
while True:
168184
frame = self.read(samples, partial=partial)
169185
if frame is not None:
@@ -176,19 +192,15 @@ def __dealloc__(self):
176192
@property
177193
def format(self):
178194
"""The :class:`.AudioFormat` of this FIFO."""
179-
if not self.ptr:
180-
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'format'")
181195
return self.template.format
196+
182197
@property
183198
def layout(self):
184199
"""The :class:`.AudioLayout` of this FIFO."""
185-
if not self.ptr:
186-
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'layout'")
187200
return self.template.layout
201+
188202
@property
189203
def sample_rate(self):
190-
if not self.ptr:
191-
raise AttributeError(f"'{__name__}.AudioFifo' object has no attribute 'sample_rate'")
192204
return self.template.sample_rate
193205

194206
@property

0 commit comments

Comments
 (0)