File Coverage

blib/lib/Audio/Wav.pm
Criterion Covered Total %
statement 34 45 75.5
branch 4 12 33.3
condition n/a
subroutine 8 9 88.8
pod 4 4 100.0
total 50 70 71.4


line stmt bran cond sub pod time code
1             package Audio::Wav;
2              
3 1     1   621 use strict;
  1         2  
  1         46  
4             eval { require warnings; }; #it's ok if we can't load warnings
5              
6 1     1   517 use Audio::Wav::Tools;
  1         2  
  1         26  
7              
8 1     1   4 use vars qw( $VERSION );
  1         1  
  1         63  
9             $VERSION = '0.14';
10              
11             BEGIN {
12              
13 1     1   2 eval { require Inline::C };
  1         353  
14 1 50       12 if($@) {
15 1         335 $Audio::Wav::_has_inline = 0;
16             } else {
17             # Inline::C is confused with multiple import calls - it seems to
18             # result in errors about @INC. hack around this by launching a
19             # seperate process instead of simply checking $@ after:
20             # eval { Inline->import(C => "int foo() { return 0; }\n"); };
21 1     1   4 use Config;
  1         1  
  1         116  
22             # don't use $^X, which breaks mod_perl - https://rt.cpan.org/Ticket/Display.html?id=62060
23 0         0 my $path = $Config{perlpath};
24 0 0       0 if ($^O ne 'VMS') {
25 0 0       0 $path .= $Config{_exe} unless $path =~ m/$Config{_exe}$/i;
26             }
27 0         0 my $inline_c_ok = `$path -e "require Inline::C; eval { Inline->import(C => q[int foo() { return 0; }]) }; print \\\$\@ ? 0 : 1"`;
28              
29 0 0       0 if($inline_c_ok) {
30 0         0 $Audio::Wav::_has_inline = 1;
31             } else {
32 0         0 warn "Inline::C installed, but your C compiler doesn't seem to work with it\n";
33 0         0 $Audio::Wav::_has_inline = 0;
34             }
35             }
36              
37             }
38              
39             =head1 NAME
40              
41             Audio::Wav - Modules for reading & writing Microsoft WAV files.
42              
43             =head1 SYNOPSIS
44              
45             # copying a file and adding some cue points to the output file
46             use Audio::Wav;
47             my $wav = new Audio::Wav;
48             my $read = $wav -> read( 'input.wav' );
49             my $write = $wav -> write( 'output.wav', $read -> details() );
50             print "input is ", $read -> length_seconds(), " seconds long\n";
51              
52             $write -> set_info( 'software' => 'Audio::Wav' );
53             my $data;
54             #read 512 bytes
55             while ( defined( $data = $read -> read_raw( 512 ) ) ) {
56             $write -> write_raw( $data );
57             }
58             my $length = $read -> length_samples();
59             my( $third, $half, $twothirds ) = map int( $length / $_ ), ( 3, 2, 1.5 );
60             my %samp_loop = (
61             'start' => $third,
62             'end' => $twothirds,
63             );
64             $write -> add_sampler_loop( %samp_loop );
65             $write -> add_cue( $half, "cue label 1", "cue note 1" );
66             $write -> finish();
67              
68              
69             # splitting a multi-channel file to separate mono files (slowly!);
70             use Audio::Wav;
71             my $read = $wav -> read( '4ch.wav' );
72             my $details = $read -> details();
73             my %out_details = map { $_ => $details -> {$_} } 'bits_sample', 'sample_rate';
74             $out_details{channels} = 1;
75             my @out_files;
76             my $in_channels = $details -> {channels};
77             foreach my $channel ( 1 .. $in_channels ) {
78             push @out_files, $wav -> write( 'multi_' . $channel . '.wav', \%out_details );
79             }
80              
81             while ( 1 ) {
82             my @channels = $read -> read();
83             last unless @channels;
84             foreach my $channel_id ( 0 .. $#channels ) {
85             $out_files[$channel_id] -> write( $channels[$channel_id] );
86             }
87             }
88              
89             # not entirely necessary as finish is done in DESTROY now (if the file hasn't been finished already).
90             foreach my $write ( @out_files ) {
91             $write -> finish();
92             }
93              
94              
95             =head1 NOTES
96              
97             All sample positions are now in sample offsets (unless option '.01compatible' is true).
98              
99             There is now *very* basic support for WAVEFORMATEXTENSIBLE (in fact it only recognises that the file is in this format).
100             The key 'wave-ex' is used in the detail hash to denote this format when reading or writing.
101             I'd like to do more with this, but don't have any hardware or software to test these files, also don't really have any spare time to do the implementation at present.
102              
103             One day I plan to learn enough C to do the sample reading/ writing in XS, but for the time being it's done using pack/ unpack in Perl and is slow.
104             Working with the raw format doesn't suffer in this way.
105              
106             It's likely that reading/ writing files with bit-depth greater than 16 won't work properly, I need to look at this at some point.
107              
108             =head1 DESCRIPTION
109              
110             These modules provide a method of reading & writing uncompressed Microsoft WAV files.
111              
112             =head1 SEE ALSO
113              
114             L
115              
116             L
117              
118             =head1 METHODS
119              
120             =head2 new
121              
122             Returns a blessed Audio::Wav object.
123             All the parameters are optional and default to 0
124              
125             my %options = (
126             '.01compatible' => 0,
127             'oldcooledithack' => 0,
128             'debug' => 0,
129             );
130             my $wav = Audio::Wav -> new( %options );
131              
132             =cut
133              
134             sub new {
135 1     1 1 228 my ($class, @args) = @_;
136 1         11 my $tools = Audio::Wav::Tools -> new( @args );
137 1         4 my $self = {
138             'tools' => $tools,
139             };
140 1         3 bless $self, $class;
141 1         4 return $self;
142             }
143              
144             =head2 write
145              
146             Returns a blessed Audio::Wav::Write object.
147              
148             my $details = {
149             'bits_sample' => 16,
150             'sample_rate' => 44100,
151             'channels' => 2,
152             };
153              
154             my $write = $wav -> write( 'testout.wav', $details );
155             my $write = Audio::Wav -> write( 'testout.wav', $details);
156             my $write = Audio::Wav -> write( 'testout.wav', $details, %options );
157              
158             where %options is in the form of arguments for L.
159              
160             See L for methods.
161              
162             =cut
163              
164             sub write {
165 2     2 1 23 my ($self, $file, $details, @args) = @_;
166 2         1088 require Audio::Wav::Write;
167 2         4 my $write;
168 2 50       8 if(ref $self) {
169 2         25 $write = Audio::Wav::Write -> new( $file, $details, $self -> {tools} );
170             } else {
171 0         0 $write = Audio::Wav::Write -> new( $file, Audio::Wav::Tools -> new( @args ) );
172             }
173 2         8 return $write;
174             }
175              
176             =head2 read
177              
178             Returns a blessed Audio::Wav::Read object.
179              
180             my $read = $wav -> read( 'testin.wav' );
181             my $read = Audio::Wav -> read( 'testin.wav' );
182             my $read = Audio::Wav -> read( 'testin.wav', %options );
183              
184             where %options is in the form of arguments for L.
185              
186             See L for methods.
187              
188             =cut
189              
190             sub read {
191 2     2 1 476 my ($self, $file, @args) = @_;
192 2         1000 require Audio::Wav::Read;
193 2         5 my $read;
194 2 100       15 if(ref $self) {
195 1         11 $read = Audio::Wav::Read -> new( $file, $self -> {tools} );
196             } else {
197 1         12 $read = Audio::Wav::Read -> new( $file, Audio::Wav::Tools -> new( @args ) );
198             }
199 2         5 return $read;
200             }
201              
202              
203             =head2 set_error_handler
204              
205             Specifies a subroutine for catching errors.
206             The subroutine should take a hash as input. The keys in the hash are 'filename', 'message' (error message), and 'warning'.
207             If no error handler is set, die and warn will be used.
208              
209             sub myErrorHandler {
210             my( %parameters ) = @_;
211             if ( $parameters{warning} ) {
212             # This is a non-critical warning
213             warn "Warning: $parameters{filename}: $parameters{message}\n";
214             } else {
215             # Critical error!
216             die "ERROR: $parameters{filename}: $parameters{message}\n";
217             }
218             }
219             $wav -> set_error_handler( \&myErrorHandler );
220              
221              
222             =cut
223              
224             sub set_error_handler {
225 0     0 1   my ($self, @args) = @_;
226 0           $self -> {tools} -> set_error_handler( @args );
227             }
228              
229             =head1 COPYRIGHT
230              
231             Copyright (c) 2007-2012 Brian Szymanski
232             Copyright (c) 1998-2006 Nick Peskett
233             Copyright (c) 2001 Kurt George Gjerde
234              
235             =head1 AUTHORS
236              
237             Nick Peskett (see http://www.peskett.co.uk/ for contact details).
238             Brian Szymanski (0.07-0.14)
239             Wolfram humann (pureperl 24 and 32 bit read support in 0.09)
240             Kurt George Gjerde . (0.02-0.03)
241              
242             see also Changes file
243              
244             =cut
245              
246             1;
247             __END__