mirror of
https://github.com/claunia/flac.git
synced 2025-12-16 18:54:26 +00:00
add support for RF64
This commit is contained in:
@@ -45,7 +45,8 @@ EXTRA_DIST = \
|
||||
test_grabbag.sh \
|
||||
test_seeking.sh \
|
||||
test_streams.sh \
|
||||
test_bins.sh
|
||||
test_bins.sh \
|
||||
write_iff.pl
|
||||
|
||||
clean-local:
|
||||
-rm -f *.raw *.flac *.oga *.ogg *.cmp *.aiff *.wav *.diff *.log *.cue core
|
||||
-rm -f *.raw *.flac *.oga *.ogg *.cmp *.aiff *.wav *.rf64 *.diff *.log *.cue core
|
||||
|
||||
@@ -52,4 +52,4 @@ valgrind: all
|
||||
release : all
|
||||
|
||||
clean:
|
||||
rm -f *.raw *.flac *.oga *.ogg *.cmp *.aiff *.wav *.diff *.log *.cue core flac-to-flac-metadata-test-files/out.* metaflac-test-files/out.*
|
||||
rm -f *.raw *.flac *.oga *.ogg *.cmp *.aiff *.wav *.rf64 *.diff *.log *.cue core flac-to-flac-metadata-test-files/out.* metaflac-test-files/out.*
|
||||
|
||||
@@ -183,12 +183,13 @@ done
|
||||
rt_test_raw ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
channels=`echo $f | awk -F- '{print $2}'`
|
||||
bps=`echo $f | awk -F- '{print $3}'`
|
||||
echo -n "round-trip test ($f) encode... "
|
||||
run_flac $SILENT --force --verify --force-raw-format --endian=little --sign=signed --sample-rate=44100 --bps=$bps --channels=$channels --no-padding --lax -o rt.flac $f || die "ERROR"
|
||||
run_flac $SILENT --force --verify --force-raw-format --endian=little --sign=signed --sample-rate=44100 --bps=$bps --channels=$channels --no-padding --lax -o rt.flac $extra $f || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --force-raw-format --endian=little --sign=signed -o rt.raw rt.flac || die "ERROR"
|
||||
run_flac $SILENT --force --decode --force-raw-format --endian=little --sign=signed -o rt.raw $extra rt.flac || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.raw || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
@@ -198,23 +199,39 @@ rt_test_raw ()
|
||||
rt_test_wav ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
echo -n "round-trip test ($f) encode... "
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $f || die "ERROR"
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $extra $f || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav rt.flac || die "ERROR"
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav $extra rt.flac || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.wav || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
rm -f rt.flac rt.wav
|
||||
}
|
||||
|
||||
rt_test_rf64 ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
echo -n "round-trip test ($f) encode... "
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $extra $f || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.rf64 $extra rt.flac || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.rf64 || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
rm -f rt.flac rt.rf64
|
||||
}
|
||||
|
||||
rt_test_aiff ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
echo -n "round-trip test ($f) encode... "
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $f || die "ERROR"
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $extra $f || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.aiff rt.flac || die "ERROR"
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.aiff $extra rt.flac || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.aiff || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
@@ -225,12 +242,13 @@ rt_test_aiff ()
|
||||
rt_test_flac ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
echo -n "round-trip test ($f->flac->flac->wav) encode... "
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $f || die "ERROR"
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.flac $extra $f || die "ERROR"
|
||||
echo -n "re-encode... "
|
||||
run_flac $SILENT --force --verify --lax -o rt2.flac rt.flac || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav rt2.flac || die "ERROR"
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav $extra rt2.flac || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.wav || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
@@ -241,12 +259,13 @@ rt_test_flac ()
|
||||
rt_test_ogg_flac ()
|
||||
{
|
||||
f="$1"
|
||||
extra="$2"
|
||||
echo -n "round-trip test ($f->oggflac->oggflac->wav) encode... "
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.oga --ogg $f || die "ERROR"
|
||||
run_flac $SILENT --force --verify --channel-map=none --no-padding --lax -o rt.oga --ogg $extra $f || die "ERROR"
|
||||
echo -n "re-encode... "
|
||||
run_flac $SILENT --force --verify --lax -o rt2.oga --ogg rt.oga || die "ERROR"
|
||||
echo -n "decode... "
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav rt2.oga || die "ERROR"
|
||||
run_flac $SILENT --force --decode --channel-map=none -o rt.wav $extra rt2.oga || die "ERROR"
|
||||
echo -n "compare... "
|
||||
cmp $f rt.wav || die "ERROR: file mismatch"
|
||||
echo "OK"
|
||||
@@ -259,6 +278,9 @@ done
|
||||
for f in rt-*.wav ; do
|
||||
rt_test_wav $f
|
||||
done
|
||||
for f in rt-*.rf64 ; do
|
||||
rt_test_rf64 $f
|
||||
done
|
||||
for f in rt-*.aiff ; do
|
||||
rt_test_aiff $f
|
||||
done
|
||||
@@ -1116,6 +1138,18 @@ for input_type in $input_types ; do
|
||||
done
|
||||
|
||||
|
||||
############################################################################
|
||||
# test --keep-foreign-metadata
|
||||
############################################################################
|
||||
|
||||
echo "Testing --keep-foreign-metadata..."
|
||||
|
||||
rt_test_wav wacky1.wav '--keep-foreign-metadata'
|
||||
rt_test_wav wacky2.wav '--keep-foreign-metadata'
|
||||
rt_test_rf64 wacky1.rf64 '--keep-foreign-metadata'
|
||||
rt_test_rf64 wacky2.rf64 '--keep-foreign-metadata'
|
||||
|
||||
|
||||
############################################################################
|
||||
# test the metadata-handling properties of flac-to-flac encoding
|
||||
############################################################################
|
||||
|
||||
168
test/write_iff.pl
Executable file
168
test/write_iff.pl
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
|
||||
require Math::BigInt;
|
||||
|
||||
my $usage = "
|
||||
$0 <format> <bps> <channels> <sample-rate> <#samples> <sample-type>
|
||||
|
||||
<format> is one of aiff,wave,rf64
|
||||
<bps> is 8,16,24,32
|
||||
<channels> is 1-8
|
||||
<sample-rate> is any 32-bit value
|
||||
<#samples> is 0-2^64-1
|
||||
<sample-type> is one of zero,rand
|
||||
|
||||
";
|
||||
|
||||
die $usage unless @ARGV == 6;
|
||||
|
||||
my %formats = ( 'aiff'=>1, 'wave'=>1, 'rf64'=>1 );
|
||||
my %sampletypes = ( 'zero'=>1, 'rand'=>1 );
|
||||
my @channelmask = ( 0, 1, 3, 7, 0x33, 0x607, 0x60f, 0, 0 ); #@@@@@@ need proper masks for 7,8
|
||||
|
||||
my ($format, $bps, $channels, $samplerate, $samples, $sampletype) = @ARGV;
|
||||
my $bigsamples = new Math::BigInt $samples;
|
||||
|
||||
die $usage unless defined $formats{$format};
|
||||
die $usage unless $bps == 8 || $bps == 16 || $bps == 24 || $bps == 32;
|
||||
die $usage unless $channels >= 1 && $channels <= 8;
|
||||
die $usage unless $samplerate >= 0 && $samplerate <= 4294967295;
|
||||
die $usage unless defined $sampletypes{$sampletype};
|
||||
|
||||
# convert bits-per-sample to bytes-per-sample
|
||||
$bps /= 8;
|
||||
|
||||
my $datasize = $samples * $bps * $channels;
|
||||
my $bigdatasize = $bigsamples * $bps * $channels;
|
||||
|
||||
my $padding = int($bigdatasize & 1? 1 : 0);
|
||||
my $wavx = ($format eq 'wave' || $format eq 'rf64') && ($channels > 2);
|
||||
|
||||
# write header
|
||||
|
||||
if ($format eq 'aiff') {
|
||||
die "sample data too big for format\n" if 46 + $datasize + $padding > 4294967295;
|
||||
# header
|
||||
print "FORM";
|
||||
print pack('N', 46 + $datasize + $padding);
|
||||
print "AIFF";
|
||||
# COMM chunk
|
||||
print "COMM";
|
||||
print pack('N', 18); # chunk size = 18
|
||||
print pack('n', $channels);
|
||||
print pack('N', $samples);
|
||||
print pack('n', $bps * 8);
|
||||
print pack_sane_extended($samplerate);
|
||||
# SSND header
|
||||
print "SSND";
|
||||
print pack('N', $datasize + 8); # chunk size
|
||||
print pack('N', 0); # ssnd_offset_size
|
||||
print pack('N', 0); # blocksize
|
||||
}
|
||||
elsif ($format eq 'wave' || $format eq 'rf64') {
|
||||
die "sample data too big for format\n" if $format eq 'wave' && ($wavx?60:36) + $datasize + $padding > 4294967295;
|
||||
# header
|
||||
if ($format eq 'wave') {
|
||||
print "RIFF";
|
||||
print pack('V', ($wavx?60:36) + $datasize + $padding);
|
||||
print "WAVE";
|
||||
}
|
||||
else {
|
||||
print "RF64";
|
||||
print pack('V', 0xffffffff);
|
||||
print "WAVE";
|
||||
# ds64 chunk
|
||||
print "ds64";
|
||||
print pack('V', 28); # chunk size
|
||||
my $bigriffsize = $bigdatasize + ($wavx?60:36) + (8+28) + $padding;
|
||||
print pack_64('V', $bigriffsize);
|
||||
print pack_64('V', $bigdatasize);
|
||||
print pack_64('V', $bigsamples);
|
||||
print pack('V', 0); # table size
|
||||
}
|
||||
# fmt chunk
|
||||
print "fmt ";
|
||||
print pack('V', $wavx?40:16); # chunk size
|
||||
print pack('v', $wavx?65534:1); # compression code
|
||||
print pack('v', $channels);
|
||||
print pack('V', $samplerate);
|
||||
print pack('V', $samplerate * $channels * $bps);
|
||||
print pack('v', $bps); # block align = channels*((bps+7)/8)
|
||||
print pack('v', $bps * 8); # bits per sample = ((bps+7)/8)*8
|
||||
if ($wavx) {
|
||||
print pack('v', 22); # cbSize
|
||||
print pack('v', $bps * 8); # validBitsPerSample
|
||||
print pack('V', $channelmask[$channels]);
|
||||
# GUID = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}
|
||||
print "\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71";
|
||||
}
|
||||
# data header
|
||||
print "data";
|
||||
print pack('V', $format eq 'wave'? $datasize : 0xffffffff);
|
||||
}
|
||||
else {
|
||||
die;
|
||||
}
|
||||
|
||||
# write sample data
|
||||
|
||||
if ($sampletype eq 'zero') {
|
||||
my $chunk = 4096;
|
||||
my $buf = pack("x[".($channels*$bps*$chunk)."]");
|
||||
for (my $s = $samples; $s > 0; $s -= $chunk) {
|
||||
if ($s < $chunk) {
|
||||
print substr($buf, 0, $channels*$bps*$s);
|
||||
}
|
||||
else {
|
||||
print $buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($sampletype eq 'rand') {
|
||||
for (my $s = 0; $s < $samples; $s++) {
|
||||
for (my $c = 0; $c < $channels; $c++) {
|
||||
for (my $b = 0; $b < $bps; $b++) {
|
||||
print pack('C', int(rand(256)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
die;
|
||||
}
|
||||
print "\x00" if $padding;
|
||||
|
||||
exit 0;
|
||||
|
||||
sub pack_sane_extended
|
||||
{
|
||||
my $val = shift;
|
||||
die unless $val > 0;
|
||||
my $shift;
|
||||
for ($shift = 0; ($val>>(31-$shift)) == 0; ++$shift) {
|
||||
}
|
||||
$val <<= $shift;
|
||||
my $exponent = 63 - ($shift + 32);
|
||||
return pack('nNN', $exponent + 16383, $val, 0);
|
||||
}
|
||||
|
||||
sub pack_64
|
||||
{
|
||||
my $c = shift;
|
||||
my $v1 = shift;
|
||||
my $v2 = $v1->copy();
|
||||
if ($c eq 'V') {
|
||||
$v1->band(0xffffffff);
|
||||
$v2->brsft(32);
|
||||
}
|
||||
elsif ($c eq 'C') {
|
||||
$v2->band(0xffffffff);
|
||||
$v1->brsft(32);
|
||||
}
|
||||
else {
|
||||
die;
|
||||
}
|
||||
return pack("$c$c", 0+$v1->bstr(), 0+$v2->bstr());
|
||||
}
|
||||
Reference in New Issue
Block a user