/[amv]/amv.pl
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /amv.pl

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 27 by dpavlin, Sat Aug 18 11:21:40 2007 UTC revision 28 by dpavlin, Sun Aug 19 11:45:39 2007 UTC
# Line 387  sub mkjpg { Line 387  sub mkjpg {
387          print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n" if $verbose;          print ">> created $frame_nr ", $no_jpeg_header ? 'raw' : '', " jpeg $path ", -s $path, " bytes\n" if $verbose;
388  }  }
389    
390  my ( $riff, $amv ) = x(12, 'Z4x4Z4');  #
391  die "$path not RIFF but $riff" if $riff ne 'RIFF';  # IMA ADPCM decoder
392  die "$path not AMV but $amv" if $amv ne 'AMV ';  #
393    
394    my @index_adjust = ( -1, -1, -1, -1, 2, 4, 6, 8 );
395    
396    my @step_size = (
397            7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
398            19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
399            50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
400            130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
401            337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
402            876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
403            2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
404            5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
405            15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
406    );
407    
408  my $apath = "$dump_dir/audio.wav";  my $pred_val = 0;
409  open(my $audio_fh, '>', $apath) || die "can't open audio file $apath: $!";  my $step_idx = 0;
410    
411  print $audio_fh pack 'a4Va4a4VvvVVv4', (  # This code is "borrowed" from the ALSA library
412          # header 'RIFF', size  # http://www.alsa-project.org
413          'RIFF',-1,  
414          # type: 'WAVE'  sub adpcm_decode_sample {
415          'WAVE',          my $code = shift;
416          'fmt ',0x14,  
417          # format: DVI (IMA) ADPCM Wave Type          my $pred_diff;  # Predicted difference to next sample
418          0x11,          my $step;               # holds previous step_size value
419          # channels  
420          1,          # Separate sign and magnitude
421          # samples/sec          my $sign = $code & 0x8;
422            $code &= 0x7;
423    
424            # Computes pred_diff = (code + 0.5) * step / 4,
425            # but see comment in adpcm_coder.
426    
427            $step = $step_size[$step_idx] || die "no step_size[$step_idx]";
428    
429            # Compute difference and new predicted value
430            $pred_diff = $step >> 3;
431            my $i = 0x4;
432            while( $i ) {
433                    if ($code & $i) {
434                            $pred_diff += $step;
435                    }
436                    $i >>= 1;
437                    $step >>= 1;
438            }
439            $pred_val += $sign ? -$pred_diff : $pred_diff;
440    
441            # Clamp output value
442            if ($pred_val > 32767) {
443                    $pred_val = 32767;
444            } elsif ($pred_val < -32768) {
445                    $pred_val = -32768;
446            }
447    
448            # Find new step_size index value
449            $step_idx += $index_adjust[$code];
450    
451            if ($step_idx < 0) {
452                    $step_idx = 0;
453            } elsif ($step_idx > 88) {
454                    $step_idx = 88;
455            }
456            return $pred_val;
457    }
458    
459    open(my $au_fh, '>', 'out.au') || die "can't open out.au: $!";
460    print $au_fh pack 'a4N5', (
461            # magic
462            '.snd',
463            # data offset
464            24,
465            # data size
466            -1,
467            # encoding - 16-bit linear PCM
468            3,
469            # sample rate
470          22050,          22050,
471          # avg. bytes/sec (for esimation)          #channels
472          11567,          1,
         # block align (size of block)  
         0x800,  
         # bits per sample (mono data)  
         4,  
         # cbSize (ADPCM with 7 soefficient pairs)  
         2,  
         # nSamplesPerBlock  
         # (((nBlockAlign - (7 * nChannels)) * 8) / (wBitsPerSample * nChannels)) + 2  
         0x0ff9,  
473  );  );
474    
475  print $audio_fh pack 'a4VVa4V', (  sub audio_frame {
476          # time length of the data in samples          my $data = shift || die "no data?";
477          'fact',4,  
478          220500,          my ( $origin, $index, $bytes ) = unpack 'ssL', substr($data,0,8);
         #  
         'data',-1,  
 );  
479    
480  my $riff_header_len = tell($audio_fh);  warn "audio_frame origin $origin index $index bytes $bytes\n";
481    hex_dump( substr($data,0,8) );
482    
483            $pred_val = $origin;
484            $step_idx = $index;
485    
486            foreach my $b ( map { ord($_) } split(//, substr($data,8)) ) {
487                    print $au_fh pack 'n', adpcm_decode_sample( $b >> 4 );          
488                    print $au_fh pack 'n', adpcm_decode_sample( $b & 15 );          
489            }
490    }
491    
492    
493    sub x_audio_frame {
494            my $data = shift || die "no data?";
495    
496            my $apath = sprintf("$dump_dir/%04d.wav", $frame_nr );
497            open(my $audio_fh, '>', $apath) || die "can't open audio file $apath: $!";
498    
499            print $audio_fh pack 'a4Va4a4VvvVVv4', (
500                    # header 'RIFF', size
501                    'RIFF',-1,
502                    # type: 'WAVE'
503                    'WAVE',
504                    'fmt ',0x14,
505                    # format: DVI (IMA) ADPCM Wave Type
506                    0x11,
507                    # channels
508                    1,
509                    # samples/sec
510                    22050,
511                    # avg. bytes/sec (for esimation)
512                    11567,
513                    # block align (size of block)
514                    0x800,
515                    # bits per sample (mono data)
516                    4,
517                    # cbSize (ADPCM with 7 soefficient pairs)
518                    2,
519                    # nSamplesPerBlock
520                    # (((nBlockAlign - (7 * nChannels)) * 8) / (wBitsPerSample * nChannels)) + 2
521                    0x03f9,
522            );
523    
524            print $audio_fh pack 'a4VVa4V', (
525                    # time length of the data in samples
526                    'fact',4,
527                    220500,
528                    #
529                    'data',-1,
530            );
531    
532            my $riff_header_len = tell($audio_fh);
533    
534            print $audio_fh $data;
535    
536            my $size = tell($audio_fh);
537            warn "## wav file $apath size: $size\n";
538    
539            seek( $audio_fh, 4, 0 );
540            print $audio_fh pack("V", $size - 8);
541            seek( $audio_fh, $riff_header_len - 4, 0 );
542            print $audio_fh pack("V", $size - $riff_header_len);
543    
544            close($audio_fh) || die "can't close audio file $apath: $!";
545    }
546    
547    #
548    # read AMV file
549    #
550    
551    my ( $riff, $amv ) = x(12, 'Z4x4Z4');
552    die "$path not RIFF but $riff" if $riff ne 'RIFF';
553    die "$path not AMV but $amv" if $amv ne 'AMV ';
554    
555  while ( ! defined($d->{eof}) ) {  while ( ! defined($d->{eof}) ) {
556          my ( $list, $name ) = x(12,'A4x4A4');          my ( $list, $name ) = x(12,'A4x4A4');
# Line 479  while ( ! defined($d->{eof}) ) { Line 602  while ( ! defined($d->{eof}) ) {
602                          }                          }
603    
604                          # remove 8 bytes of something                          # remove 8 bytes of something
605                          $audio_frame = substr( $audio_frame, 8 );  #                       $audio_frame = substr( $audio_frame, 8 );
606    
607                          if ( length($audio_frame) % 2 == 0 ) {                          if ( length($audio_frame) % 2 == 0 ) {
608                                  print "#### even sized frame!";                                  print "#### even sized frame!";
# Line 487  while ( ! defined($d->{eof}) ) { Line 610  while ( ! defined($d->{eof}) ) {
610                          }                          }
611    
612  #                       print $audio_fh mp3_frame;  #                       print $audio_fh mp3_frame;
613                          print $audio_fh $audio_frame || die "can't write audio frame in $apath: $!";                          audio_frame( $audio_frame );
614    
615                          $frame_nr++;                          $frame_nr++;
616                  };                  };
# Line 500  while ( ! defined($d->{eof}) ) { Line 623  while ( ! defined($d->{eof}) ) {
623  my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";  my $cmd = "ffmpeg -i $dump_dir/%04d.jpg -r 16 -y $dump_avi";
624  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";  system($cmd) == 0 || die "can't convert frames to avi using $cmd: $!";
625    
626  my $size = tell($audio_fh);  print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, "\n";
 warn "## wav file size: $size\n";  
   
 seek( $audio_fh, 4, 0 );  
 print $audio_fh pack("V", $size - 8);  
 seek( $audio_fh, $riff_header_len - 4, 0 );  
 print $audio_fh pack("V", $size - $riff_header_len);  
   
 close($audio_fh) || die "can't close audio file $apath: $!";  
   
 print ">>>> created $frame_nr frames $dump_avi ", -s $dump_avi, " and $apath ", -s $apath, "\n";  

Legend:
Removed from v.27  
changed lines
  Added in v.28

  ViewVC Help
Powered by ViewVC 1.1.26