File Coverage

blib/lib/Audio/Extract/PCM/Backend.pm
Criterion Covered Total %
statement 9 44 20.4
branch 0 20 0.0
condition n/a
subroutine 3 7 42.8
pod 4 4 100.0
total 16 75 21.3


line stmt bran cond sub pod time code
1             package Audio::Extract::PCM::Backend;
2 2     2   14 use strict;
  2         4  
  2         80  
3 2     2   12 use warnings;
  2         4  
  2         136  
4 2     2   12 use base qw(Class::Accessor::Fast);
  2         2  
  2         1260  
5              
6             __PACKAGE__->mk_accessors(qw(filename error format));
7              
8             =head1 NAME
9              
10             Audio::Extract::PCM::Backend - base class for audio extraction backends
11              
12             =head1 SYNOPSIS
13              
14             This is the base class for the backends for L. The
15             backend classes provide a common interface to other modules:
16              
17             =over 8
18              
19             =item *
20              
21             L - uses L
22              
23             =item *
24              
25             L - uses the external "sox" program
26              
27             =item *
28              
29             L - uses L
30              
31             =item *
32              
33             L - uses L
34              
35             =back
36              
37             Apart from these backends that are provided with this distribution, it should
38             be fairly easy (and soon fully documented) to design backends to interface with
39             other modules/libraries/codecs.
40              
41             Ideally, L should find an appropriate backend for a given
42             file automatically.
43              
44             =head1 INHERITANCE
45              
46             This module inherits from L. If you write your own
47             backend, you should inherit from this class and thus you can add your own
48             accessors using CA's API.
49              
50             =head1 ACCESSORS
51              
52             =head2 filename
53              
54             The file name. This is expected to be given to the constructor.
55              
56             =head2 error
57              
58             Contains the description of the last error.
59              
60             =head2 format
61              
62             Contains a L object describing the format of the
63             PCM data after a successfull call to L or L.
64              
65             =head1 METHODS
66              
67             =head2 new
68              
69             Constructor. Accepts key-value pairs as arguments (i.e. not a hash reference
70             like Class::Accessor's constructor).
71              
72             =cut
73              
74             sub new {
75 0     0 1   my $class = shift;
76 0           my (%args) = @_;
77              
78 0           return $class->SUPER::new(\%args);
79             }
80              
81              
82             =head2 pcm
83              
84             Extract all pcm data from the file.
85              
86             In your backend, you should not override this method. Rather you provide
87             C and (optionally) C methods. If you provide a
88             C method, it will be used to extract the audio data. Otherwise, your
89             C and C methods will be used.
90              
91             The single parameter for both C and C is a
92             L object which describes the desired format of the
93             PCM data.
94              
95             If you provide a C method, it is supposed to store the actual PCM
96             format with the L accessor.
97              
98             The return value is a reference to the PCM string buffer.
99              
100             On error, C is returned (in scalar context) and the error should be set
101             with the C accessor.
102              
103             =cut
104              
105             sub pcm {
106 0     0 1   my $this = shift;
107              
108 0 0         unless ($this->can('pcm_back')) {
109              
110 0           my $ret = $this->open_back(@_);
111 0 0         return $ret unless $ret;
112              
113 0           $this->format($ret);
114              
115 0           my %foohash = (buf => '');
116 0           my $bufref = \$foohash{buf};
117              
118 0           1 while $this->read_back($$bufref, append => 1, bytes => 8192);
119              
120 0           return $bufref;
121             }
122              
123 0           return $this->pcm_back(@_);
124             }
125              
126              
127             =head2 open
128              
129             Open, i.e. prepare for L.
130              
131             You should not override this method but rather provide a C method
132             with the same specifications.
133              
134             The argument is a L object which describes the
135             desired format of the PCM data.
136              
137             The return value is another format object which describes the actual format of
138             the audio data. You need not bother setting the L accessor in
139             C; C does this for you.
140              
141             On error, C is returned (in scalar context) and the error should be set
142             with the C accessor.
143              
144             If the backend decides that it cannot open the file but some other backend
145             might be able to, the string "trynext" should be returned. If C
146             returns a format that does not satisfy the format request, C treats this
147             as though C had returned "trynext".
148              
149             =cut
150              
151              
152             sub open {
153 0     0 1   my $this = shift;
154 0           my ($format) = @_;
155              
156 0           my $ret = $this->open_back(@_);
157 0 0         return () unless defined $ret;
158              
159 0 0         return 'trynext' unless $format->satisfied($ret);
160              
161 0 0         $this->format($ret) if $ret;
162              
163 0           return $ret;
164             }
165              
166              
167             =head2 read
168              
169             The backend should provide a C method which will be called like this:
170              
171             $backend->read_back(
172             $buffer, # lvalue
173              
174             bytes => 100000, # how many bytes to read at least. Should default
175             # to all bytes
176              
177             append => 1, # If this is specified, the buffer shall be appended to.
178             # Some backends can do this efficiently.
179             );
180              
181             The buffer shall be an lvalue, but the backend need not care about "strange"
182             lvalues like C. This would be too troublesome because many backends
183             make use of XS modules.
184              
185             In scalar context, C shall return the number of bytes read, 0 on eof
186             and C on error.
187              
188             =cut
189              
190             sub read {
191 0     0 1   my $this = shift;
192 0           my $buf = \shift;
193 0           my (%args) = @_;
194 0           my %orig_args = %args;
195              
196 0           my $format = $this->format;
197              
198 0           my $bytes = $args{bytes};
199 0 0         unless (defined $bytes) {
200 0 0         if (defined $args{seconds}) {
201 0           $bytes = int(delete ($args{seconds})
202             * $format->freq * $format->channels * $format->samplesize);
203             }
204             }
205 0 0         $args{bytes} = $bytes if defined $bytes;
206              
207 0           my $bytes_read = $this->read_back($$buf, %args);
208              
209 0 0         return () unless defined $bytes_read;
210              
211 0 0         if (exists $orig_args{seconds}) {
212 0           return $bytes_read / ($format->freq * $format->channels * $format->samplesize);
213             } else {
214 0           return $bytes_read;
215             }
216             }
217              
218              
219             =head2 used_versions
220              
221             Should be implemented by the backends to describe the versions of the modules,
222             libraries and other pieces of software that are being used.
223              
224             Should return a hash reference where the keys are the names of the products,
225             and the values are their versions. The versions may be strings of any kind (or
226             objects that can be stringified). The intend is to provide an easy way to show
227             the user what software was used.
228              
229             =cut
230              
231              
232             1