Class: Audio::MPEG::Encoder
- Inherits:
-
Object
- Object
- Audio::MPEG::Encoder
- Defined in:
- lib/icanhasaudio/mpeg/encoder.rb,
ext/icanhasaudio/audio_mpeg_encoder.c
Constant Summary collapse
- WAV_ID_RIFF =
0x52494646
- WAV_ID_WAVE =
“WAVE”
0x57415645
- WAV_ID_FMT =
“fmt ”
0x666d7420
- WAV_ID_DATA =
“data”
0x64617461
- IFF_ID_FORM =
“FORM”
0x464f524d
- IFF_ID_AIFF =
“AIFF”
0x41494646
- IFF_ID_AIFC =
“AIFC”
0x41494643
- IFF_ID_COMM =
“COMM”
0x434f4d4d
- IFF_ID_SSND =
“SSND”
0x53534e44
- IFF_ID_NONE =
“NONE” AIFF-C data format
0x4e4f4e45
- IFF_ID_2CBE =
“twos” AIFF-C data format
0x74776f73
- IFF_ID_2CLE =
“sowt” AIFF-C data format
0x736f7774
- VBR_OFF =
0
- VBR_NORMAL =
2
- VBR_FAST =
4
- MODE_NAMES =
[ [ 'stereo', 'j-stereo', 'dual-ch', 'single-ch' ], [ 'stereo', 'force-ms', 'dual-ch', 'single-ch' ], ]
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#pcmbitwidth ⇒ Object
Returns the value of attribute pcmbitwidth.
Class Method Summary collapse
Instance Method Summary collapse
-
#album= ⇒ Object
Set the ID3 album.
-
#artist= ⇒ Object
Set the ID3 artist.
-
#bitrate ⇒ Object
Get the bitrate.
-
#bitrate= ⇒ Object
Set the bitrate.
- #encode(infile, outfile) ⇒ Object
-
#genre= ⇒ Object
Set the ID3 genre.
-
#initialize ⇒ Encoder
constructor
A new instance of Encoder.
-
#print_config ⇒ Object
Print the encoder configuration.
-
#title= ⇒ Object
Set the ID3 title.
-
#track= ⇒ Object
Set the ID3 track.
-
#vbr_hard_min= ⇒ Object
Strictly enforce the vbr min bitrate.
-
#vbr_hard_min? ⇒ Boolean
Get the hard minimum flag.
-
#vbr_max_bitrate ⇒ Object
Get the maximum vbr bitrate.
-
#vbr_max_bitrate= ⇒ Object
Set the maximum vbr bitrate.
-
#vbr_min_bitrate ⇒ Object
Get the minimum vbr bitrate.
-
#vbr_min_bitrate= ⇒ Object
Set the minimum vbr bitrate.
-
#quality ⇒ Object
Get the VBR quality.
-
#quality= ⇒ Object
Set the VBR quality.
-
#vbr_type ⇒ Object
Get the type of VBR.
-
#vbr_type= ⇒ Object
Set the type of VBR.
-
#year= ⇒ Object
Set the ID3 year.
Constructor Details
#initialize ⇒ Encoder
Returns a new instance of Encoder.
31 32 33 34 35 36 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 31 def initialize @pcmbitwidth = 16 @logger = nil self.vbr_quality = 2 self.vbr_type = VBR_NORMAL end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
30 31 32 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 30 def logger @logger end |
#pcmbitwidth ⇒ Object
Returns the value of attribute pcmbitwidth.
29 30 31 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 29 def pcmbitwidth @pcmbitwidth end |
Class Method Details
.parse_aiff_header(file) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 115 def parse_aiff_header(file) chunk_size = file.read(4).unpack('N').first type_id = file.read(4).unpack('N').first raise unless [IFF_ID_AIFF, IFF_ID_AIFC].any? { |x| type_id == x } sub_size = 0 sample_type = nil sample_size = nil num_channels = nil block_size = nil sample_rate = nil is_aiff = false while chunk_size > 0 type = file.read(4).unpack('N').first chunk_size -= 4 case type when IFF_ID_COMM sub_size = file.read(4).unpack('N').first chunk_size -= 4 num_channels = file.read(2).unpack('n').first sub_size -= 2 num_sample_frames = file.read(4).unpack('N').first sub_size -= 4 sample_size = file.read(2).unpack('n').first sub_size -= 2 sample_rate = unpack_ieee(file.read(10)) sub_size -= 10 if type_id == IFF_ID_AIFC data_type = file.read(4).unpack('N').first sub_size -=4 raise unless [ IFF_ID_2CLE, IFF_ID_2CBE, IFF_ID_NONE, ].any? { |x| data_type == x } #if sample_size == 16 # swap bytes.... end file.read(sub_size) when IFF_ID_SSND sub_size = file.read(4).unpack('N').first chunk_size -= sub_size block_offset = file.read(4).unpack('N').first sub_size -= 4 block_size = file.read(4).unpack('N').first sub_size -= 4 sample_type = IFF_ID_SSND file.read(block_offset) is_aiff = true break else sub_size = file.read(4).unpack('N').first chunk_size -= sub_size file.read(sub_size) end end # Validate the header if is_aiff raise "Sound data is not PCM" unless sample_type == IFF_ID_SSND raise "Sound data is not 16 bits" unless sample_size == 16 unless num_channels == 1 || num_channels == 2 raise "Sound data is not mono or stereo" end raise "Block size is not 0 bytes" unless block_size == 0 end { :num_channels => num_channels, :in_samplerate => simple_rate.to_i, :num_samples => num_sample_frames, :bit_width => sample_size, } end |
.parse_wave_header(file) ⇒ Object
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 204 def parse_wave_header(file) format_tag = nil channels = nil samples_per_sec = nil avg_bytes_per_sec = nil block_align = nil bits_per_sample = nil is_wav = false data_length = 0 file_length = file.read(4).unpack('N').first raise "Corrupt wave" if file.read(4).unpack('N').first != WAV_ID_WAVE 20.times { type = file.read(4).unpack('N').first case type when WAV_ID_FMT sub_size = file.read(4).unpack('V').first raise "Corrupt wave" if sub_size < 16 ( format_tag, channels, samples_per_sec, avg_bytes_per_sec, block_align, bits_per_sample) = *(file.read(16).unpack('vvVVvv')) sub_size -= 16 file.read(sub_size) if sub_size > 0 when WAV_ID_DATA sub_size = file.read(4).unpack('V').first data_length = sub_size is_wav = true break; else sub_size = file.read(4).unpack('V').first file.read(sub_size) end } raise "Unsupported format" unless format_tag == 1 raise unless is_wav { :num_channels => channels, :in_samplerate => samples_per_sec, :bytes_in_seconds => data_length, :milliseconds => (data_length/2)/(samples_per_sec/1000)/2, :num_samples => data_length / (channels*((bits_per_sample+7)/8)), :bit_width => bits_per_sample, } end |
.unpack_ieee(data) ⇒ Object
198 199 200 201 202 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 198 def unpack_ieee(data) (expon, hi_mant, lo_mant) = data.unpack('nNN') expon -= 16383 hi_mant * (2 ** (expon -= 31)) + lo_mant * (2 ** (expon -= 32)) end |
Instance Method Details
#album= ⇒ Object
Set the ID3 album.
239 240 241 242 243 244 245 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 239
static VALUE set_album(VALUE self, VALUE album) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
id3tag_set_album(gfp, StringValuePtr(album));
return album;
}
|
#artist= ⇒ Object
Set the ID3 artist.
211 212 213 214 215 216 217 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 211
static VALUE set_artist(VALUE self, VALUE artist) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
id3tag_set_artist(gfp, StringValuePtr(artist));
return artist;
}
|
#bitrate ⇒ Object
Get the bitrate.
130 131 132 133 134 135 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 130 static VALUE get_bitrate(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); return INT2NUM(lame_get_brate(gfp)); } |
#bitrate= ⇒ Object
Set the bitrate.
115 116 117 118 119 120 121 122 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 115
static VALUE set_bitrate(VALUE self, VALUE brate) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_brate(gfp, NUM2INT(brate));
lame_set_VBR_min_bitrate_kbps(gfp, lame_get_brate(gfp));
return brate;
}
|
#encode(infile, outfile) ⇒ Object
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 |
# File 'lib/icanhasaudio/mpeg/encoder.rb', line 38 def encode(infile, outfile) raise "Out file must be a FILE. :-(" unless outfile.is_a?(File) num_samples = 0xFFFFFFFF parse_header(infile) init_params logger.debug(encoding_info) if logger num_samples_read = 0 sw = case @pcmbitwidth when 8 32 - 8 when 16 32 - 16 when 24 32 - 24 end while !infile.eof? tmp_num_samples = num_samples() samples_to_read = framesize() remaining = tmp_num_samples - [tmp_num_samples, num_samples_read].min if remaining < framesize && 0 != tmp_num_samples samples_to_read = remaining end read_size = num_channels * samples_to_read * (pcmbitwidth / 8) samples = infile.read(read_size) samples_read = samples.length / num_channels buffers = [[], []] samples.unpack('v*').each_with_index do |b,i| (buffers[(i % 2)]) << (b << sw) end outfile.write(encode_buffer(buffers[0], buffers[1])) end outfile.write(flush()) (outfile) if write_vbr_tag? end |
#genre= ⇒ Object
Set the ID3 genre.
287 288 289 290 291 292 293 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 287
static VALUE set_genre(VALUE self, VALUE genre) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
id3tag_set_genre(gfp, StringValuePtr(genre));
return genre;
}
|
#print_config ⇒ Object
Print the encoder configuration.
197 198 199 200 201 202 203 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 197 static VALUE print_config(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); lame_print_config(gfp); return Qnil; } |
#title= ⇒ Object
Set the ID3 title.
225 226 227 228 229 230 231 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 225
static VALUE set_title(VALUE self, VALUE title) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
id3tag_set_title(gfp, StringValuePtr(title));
return title;
}
|
#track= ⇒ Object
Set the ID3 track.
268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 268
static VALUE set_track(VALUE self, VALUE track) {
lame_global_flags * gfp;
int track_number = NUM2INT(track);
if(track < 0 || track > 255)
rb_raise(rb_eRuntimeError, "Track must be between 0 and 255.\n");
Data_Get_Struct(self, lame_global_flags, gfp);
VALUE track_string = rb_funcall(track, rb_intern("to_s"), 0);
id3tag_set_track(gfp, StringValuePtr(track_string));
return track;
}
|
#vbr_hard_min= ⇒ Object
Strictly enforce the vbr min bitrate. Normally it will be violated for analog silence.
31 32 33 34 35 36 37 38 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 31
static VALUE set_vbr_hard_min(VALUE self, VALUE boolean)
{
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_VBR_hard_min(gfp, boolean == Qtrue ? 1 : 0);
return boolean;
}
|
#vbr_hard_min? ⇒ Boolean
Get the hard minimum flag.
46 47 48 49 50 51 52 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 46
static VALUE get_vbr_hard_min(VALUE self)
{
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
return lame_get_VBR_hard_min(gfp) == 0 ? Qfalse : Qtrue;
}
|
#vbr_max_bitrate ⇒ Object
Get the maximum vbr bitrate.
75 76 77 78 79 80 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 75 static VALUE get_vbr_max_bitrate(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); return INT2NUM(lame_get_VBR_max_bitrate_kbps(gfp)); } |
#vbr_max_bitrate= ⇒ Object
Set the maximum vbr bitrate.
60 61 62 63 64 65 66 67 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 60
static VALUE set_vbr_max_bitrate(VALUE self, VALUE brate)
{
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_VBR_max_bitrate_kbps(gfp, NUM2INT(brate));
return brate;
}
|
#vbr_min_bitrate ⇒ Object
Get the minimum vbr bitrate.
102 103 104 105 106 107 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 102 static VALUE get_vbr_min_bitrate(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); return INT2NUM(lame_get_VBR_min_bitrate_kbps(gfp)); } |
#vbr_min_bitrate= ⇒ Object
Set the minimum vbr bitrate.
88 89 90 91 92 93 94 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 88
static VALUE set_vbr_min_bitrate(VALUE self, VALUE brate) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_VBR_min_bitrate_kbps(gfp, NUM2INT(brate));
return brate;
}
|
#quality ⇒ Object
Get the VBR quality. 0 = highest, 9 = lowest
157 158 159 160 161 162 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 157 static VALUE get_vbr_quality(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); return INT2NUM(lame_get_VBR_q(gfp)); } |
#quality= ⇒ Object
Set the VBR quality. 0 = highest, 9 = lowest
143 144 145 146 147 148 149 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 143
static VALUE set_vbr_quality(VALUE self, VALUE quality) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_VBR_q(gfp, NUM2INT(quality));
return quality;
}
|
#vbr_type ⇒ Object
Get the type of VBR.
184 185 186 187 188 189 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 184 static VALUE get_vbr_type(VALUE self) { lame_global_flags * gfp; Data_Get_Struct(self, lame_global_flags, gfp); return INT2NUM(lame_get_VBR(gfp)); } |
#vbr_type= ⇒ Object
Set the type of VBR. Must be VBR_OFF, VBR_NORMAL, or VBR_FAST
170 171 172 173 174 175 176 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 170
static VALUE set_vbr_type(VALUE self, VALUE type) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
lame_set_VBR(gfp, NUM2INT(type));
return type;
}
|
#year= ⇒ Object
Set the ID3 year.
253 254 255 256 257 258 259 260 |
# File 'ext/icanhasaudio/audio_mpeg_encoder.c', line 253
static VALUE set_year(VALUE self, VALUE year) {
lame_global_flags * gfp;
Data_Get_Struct(self, lame_global_flags, gfp);
VALUE year_string = rb_funcall(year, rb_intern("to_s"), 0);
id3tag_set_year(gfp, StringValuePtr(year_string));
return year;
}
|