1
- //! wave-inter .rs
1
+ //! wave-deinter .rs
2
2
//! (c) 2021 Jamie Hardt. All rights reserved.
3
3
//!
4
- //! This program demonstrats combining several wave files into a single
5
- //! polyphonic wave file .
4
+ //! This program demonstrates splitting a multichannel file into separate monophonic files for each
5
+ //! individual channel .
6
6
7
- use std:: io;
7
+ use std:: io:: { Read , Seek } ;
8
8
use std:: path:: Path ;
9
9
10
10
extern crate bwavfile;
11
- use bwavfile:: { ChannelDescriptor , ChannelMask , Error , WaveFmt , WaveReader , WaveWriter } ;
11
+ use bwavfile:: {
12
+ ChannelDescriptor , ChannelMask , CommonFormat , Error , Sample , WaveFmt , WaveReader , WaveWriter ,
13
+ I24 ,
14
+ } ;
12
15
13
16
#[ macro_use]
14
17
extern crate clap;
@@ -48,17 +51,25 @@ fn name_suffix(
48
51
}
49
52
}
50
53
51
- fn process_file ( infile : & str , delim : & str , numeric_channel_names : bool ) -> Result < ( ) , Error > {
52
- let mut input_file = WaveReader :: open ( infile) ?;
54
+ fn deinterleave_file < S , R > (
55
+ mut input_file : WaveReader < R > ,
56
+ input_format : WaveFmt ,
57
+ settings : Settings ,
58
+ ) -> Result < ( ) , Error >
59
+ where
60
+ S : Sample ,
61
+ R : Read + Seek ,
62
+ {
63
+ let frames_per_read = 4096 ;
53
64
let channel_desc = input_file. channels ( ) ?;
54
- let input_format = input_file . format ( ) ? ;
65
+ let channel_count = channel_desc . len ( ) ;
55
66
56
67
if channel_desc. len ( ) == 1 {
57
68
println ! ( "Input file in monoaural, exiting." ) ;
58
69
return Ok ( ( ) ) ;
59
70
}
60
71
61
- let infile_path = Path :: new ( infile ) ;
72
+ let infile_path = Path :: new ( & settings . input_path ) ;
62
73
let basename = infile_path
63
74
. file_stem ( )
64
75
. expect ( "Unable to extract file basename" )
@@ -68,38 +79,91 @@ fn process_file(infile: &str, delim: &str, numeric_channel_names: bool) -> Resul
68
79
. parent ( )
69
80
. expect ( "Unable to derive parent directory" ) ;
70
81
71
- let ouptut_format =
72
- WaveFmt :: new_pcm_mono ( input_format. sample_rate , input_format. bits_per_sample ) ;
73
- let mut input_wave_reader = input_file. audio_frame_reader ( ) ?;
74
-
75
- for ( n, channel) in channel_desc. iter ( ) . enumerate ( ) {
76
- let suffix = name_suffix ( numeric_channel_names, delim, n + 1 , channel) ;
77
- let outfile_name = output_dir
78
- . join ( format ! ( "{}{}.wav" , basename, suffix) )
79
- . into_os_string ( )
80
- . into_string ( )
81
- . unwrap ( ) ;
82
-
83
- println ! ( "Will create file {}" , outfile_name) ;
84
-
85
- let output_file =
86
- WaveWriter :: create ( & outfile_name, ouptut_format) . expect ( "Failed to create new file" ) ;
82
+ let output_block_alignment = input_format. bits_per_sample / 8 ;
83
+ let output_format = WaveFmt {
84
+ channel_count : 1 ,
85
+ block_alignment : output_block_alignment,
86
+ bytes_per_second : output_block_alignment as u32 * input_format. sample_rate ,
87
+ ..input_format
88
+ } ;
89
+ let mut reader = input_file. audio_frame_reader ( ) ?;
90
+ let mut writers = channel_desc
91
+ . iter ( )
92
+ . enumerate ( )
93
+ . map ( |( n, channel) | {
94
+ let suffix = name_suffix (
95
+ settings. use_numeric_names ,
96
+ & settings. delimiter ,
97
+ n + 1 ,
98
+ channel,
99
+ ) ;
100
+ let outfile_name = output_dir
101
+ . join ( format ! ( "{}{}.wav" , basename, suffix) )
102
+ . into_os_string ( )
103
+ . into_string ( )
104
+ . unwrap ( ) ;
105
+
106
+ println ! ( "Will create file {}" , outfile_name) ;
107
+
108
+ WaveWriter :: create ( & outfile_name, output_format)
109
+ . expect ( "Failed to create new file" )
110
+ . audio_frame_writer ( )
111
+ } )
112
+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
113
+
114
+ let mut input_buffer = vec ! [ S :: EQUILIBRIUM ; frames_per_read * channel_count] ;
115
+ let mut output_buffer = vec ! [ S :: EQUILIBRIUM ; frames_per_read] ;
116
+
117
+ loop {
118
+ let frames_read = reader. read_frames ( & mut input_buffer) ? as usize ;
119
+ if frames_read == 0 {
120
+ break ;
121
+ }
87
122
88
- let mut output_wave_writer = output_file. audio_frame_writer ( ) ?;
89
- let mut buffer = input_format. create_frame_buffer ( 1 ) ;
123
+ output_buffer. resize ( frames_read, S :: EQUILIBRIUM ) ;
90
124
91
- while input_wave_reader. read_integer_frame ( & mut buffer) ? > 0 {
92
- output_wave_writer. write_integer_frames ( & buffer[ n..=n] ) ?;
125
+ for ( n, writer) in writers. iter_mut ( ) . enumerate ( ) {
126
+ for ( output, input) in output_buffer
127
+ . iter_mut ( )
128
+ . zip ( input_buffer. iter ( ) . skip ( n) . step_by ( channel_count) )
129
+ {
130
+ * output = * input;
131
+ }
132
+ writer. write_frames ( & output_buffer) ?;
93
133
}
134
+ }
94
135
95
- output_wave_writer . end ( ) ? ;
96
- input_wave_reader . locate ( 0 ) ?;
136
+ for writer in writers . drain ( .. ) {
137
+ writer . end ( ) ?;
97
138
}
98
139
99
140
Ok ( ( ) )
100
141
}
101
142
102
- fn main ( ) -> io:: Result < ( ) > {
143
+ fn process_file < R > ( mut input : WaveReader < R > , settings : Settings ) -> Result < ( ) , Error >
144
+ where
145
+ R : Read + Seek ,
146
+ {
147
+ let format = input. format ( ) ?;
148
+
149
+ use CommonFormat :: * ;
150
+ match ( format. common_format ( ) , format. bits_per_sample ) {
151
+ ( IntegerPCM , 8 ) => deinterleave_file :: < u8 , R > ( input, format, settings) ,
152
+ ( IntegerPCM , 16 ) => deinterleave_file :: < i16 , R > ( input, format, settings) ,
153
+ ( IntegerPCM , 24 ) => deinterleave_file :: < I24 , R > ( input, format, settings) ,
154
+ ( IntegerPCM , 32 ) => deinterleave_file :: < i32 , R > ( input, format, settings) ,
155
+ ( IeeeFloatPCM , 32 ) => deinterleave_file :: < f32 , R > ( input, format, settings) ,
156
+ other => panic ! ( "Unsupported format: {:?}" , other) ,
157
+ }
158
+ }
159
+
160
+ struct Settings {
161
+ input_path : String ,
162
+ delimiter : String ,
163
+ use_numeric_names : bool ,
164
+ }
165
+
166
+ fn main ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
103
167
let matches = App :: new ( "wave-deinter" )
104
168
. version ( crate_version ! ( ) )
105
169
. author ( crate_authors ! ( ) )
@@ -126,13 +190,12 @@ fn main() -> io::Result<()> {
126
190
)
127
191
. get_matches ( ) ;
128
192
129
- let delimiter = matches. value_of ( "channel_delimiter" ) . unwrap ( ) ;
130
- let use_numeric_names = matches. is_present ( "numeric_names" ) ;
131
- let infile = matches. value_of ( "INPUT" ) . unwrap ( ) ;
193
+ let settings = Settings {
194
+ input_path : matches. value_of ( "INPUT" ) . unwrap ( ) . into ( ) ,
195
+ delimiter : matches. value_of ( "channel_delimiter" ) . unwrap ( ) . into ( ) ,
196
+ use_numeric_names : matches. is_present ( "numeric_names" ) ,
197
+ } ;
132
198
133
- match process_file ( infile, delimiter, use_numeric_names) {
134
- Err ( Error :: IOError ( io) ) => Err ( io) ,
135
- Err ( e) => panic ! ( "Error: {:?}" , e) ,
136
- Ok ( ( ) ) => Ok ( ( ) ) ,
137
- }
199
+ process_file ( WaveReader :: open ( & settings. input_path ) ?, settings) ?;
200
+ Ok ( ( ) )
138
201
}
0 commit comments