Skip to content

Instantly share code, notes, and snippets.

@tateisu
Created July 26, 2013 02:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tateisu/6085481 to your computer and use it in GitHub Desktop.
Save tateisu/6085481 to your computer and use it in GitHub Desktop.
foo_dsp_xgeq でエクスポートしたデータに対して、指定チャネルの全バンドに一定の値を加算するスクリプト usage: xgeq-offset.pl infile (outfile (ch:delta) (ch:delta) ...) example: perl xgeq-offset.pl infile.xgeq outfile.xgeq 0:-3 1:-3.5
#!perl --
use strict;
use warnings;
use Carp;
sub hexFromBytes($){ return unpack("H*",$_[0]); }
sub bytesFromHex($){ return pack("H*",$_[0]); }
sub bytesFromFloat($){ return pack('f',@_); }
sub intFromBytes($){
length($_[0]) == 4 and return unpack("l",$_[0]);
length($_[0]) == 2 and return unpack("s",$_[0]);
length($_[0]) == 1 and return unpack("C",$_[0]);
croak "intFromBytes : bad bytes length ";
}
# find byte pattern and move offset to end of it
sub skip($$$){
my($src,$rOffset,$needle)=@_;
my $pos = index($src,$needle,$$rOffset);
$pos >= 0 or die "cannot find ",length($needle)," bytes sign from offset ",$$rOffset,".\n";
$$rOffset = $pos + length($needle);
}
# get bytes and move offset to end of it
sub getBytes($$$){
my($src,$rOffset,$length)=@_;
length($src) >= $$rOffset + $length or die "unexpect end of data. read $length bytes from offset ",$$rOffset,".\n";
my $result = substr($src,$$rOffset,$length);
$$rOffset += $length;
return $result;
}
my $clip_min = -1200;
my $clip_max = 1200;
my $infile = shift;
my $outfile = shift;
$infile or die "usage: $0 infile (outfile (channel:delta)...)\n";
# read infile
my $data;
{
open(my $fh,"<",$infile) or die "$infile $!\n";
binmode $fh;
my $size = -s $fh;
my $readed = read($fh,$data,4096,0);
close($fh) or die "$infile $!\n";
$size == $readed or die "incorrect read size: $infile\n";
printf "read length=%d\n",length($data);
}
# parse *.xgeq file
my @item_list;
{
# 先頭
my $p = 0;
#
skip $data,\$p,"\x0d\x0a";
#
skip $data,\$p,"\x0d\x0a";
# I don't know about these byte meaning what.
if(0){
my $nazo = bytesFromHex("763A0CE7A7889F41A2EAB00C3A9AC7421601000003000000");
skip $data,\$p,$nazo;
}else{
$p += 24;
}
#
my $is_stereo = intFromBytes getBytes $data,\$p, 4;
printf "is_stereo=%s\n",$is_stereo;
#
my $channel_count = intFromBytes getBytes $data,\$p, 4;
printf "channel_count=%s\n",$channel_count;
# read each channel
for(my $ch = 0;$ch < $channel_count ; ++ $ch ){
my $item = {};
push @item_list,$item;
#
$item->{preamp} = intFromBytes getBytes $data,\$p, 4;
printf "ch[$ch] preamp=%s\n",$item->{preamp};
#
$item->{auto_volume} = intFromBytes getBytes $data,\$p, 1;
printf "ch[$ch] auto_volume=%s\n",$item->{auto_volume};
#
my $band_count = intFromBytes getBytes $data,\$p, 4;
printf "ch[$ch] band_count=%s\n",$band_count;
# read each band
$item->{start_pos} = $p;
$item->{value_min}= 0x7fffffff;
$item->{value_max}= -0x7fffffff;
my $band_list = $item->{band_list} = [];
for(my $band =0;$band < $band_count; ++$band ){
my $value = intFromBytes getBytes $data,\$p, 4;
printf "ch[$ch] band[$band] value=%s\n",$value;
push @$band_list, $value;
$item->{value_min} < $value or $item->{value_min} = $value;
$item->{value_max} > $value or $item->{value_max} = $value;
}
}
}
if( $outfile ){
# apply delta to specified channel
for( @ARGV ){
# read ch:delta pair from arguments
/(\d+):([+-]?\d*\.?\d*)/ or die "unrecognized argument '$_'\n";
my($ch,$delta)=($1,$2);
$delta=~/\d/ or die "unrecognized argument '$_'\n";
printf "channel=%d, delta=%d\n",$ch,$delta;
# find specified channel
my $item = $item_list[$ch] or die "incorrect channel spec: $ch\n";
# convert delta to internal format. ex: 12.00db => 1200
$delta = int($delta*100);
# clip delta with min,max value
if( $item->{value_min} + $delta < $clip_min ){
$delta = $clip_min - $item->{value_min};
printf "delta clipped to %.2f\n",$delta/100;
}elsif( $item->{value_max} + $delta > $clip_max ){
$delta = $clip_max - $item->{value_max};
printf "delta clipped to %.2f\n",$delta/100;
}
# update each band
my $list = $item->{band_list};
for(my $i=0 ; $i < @$list ; ++$i ){
$list->[$i] += $delta;
}
}
# re-encode band data into byte buffer
for my $item (@item_list ){
my $p = $item->{start_pos};
for my $value ( @{ $item->{band_list} } ){
my $bytes = pack "l",$value;
substr $data , $p, length($bytes),$bytes ;
$p += length $bytes;
}
}
# write to output
open(my $fh,">",$outfile) or die "$outfile $!\n";
binmode $fh;
print $fh $data;
close($fh) or die "$outfile $!\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment