Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xiph.Org
flac
Commits
b04ce04d
Commit
b04ce04d
authored
Dec 12, 2002
by
Josh Coalson
Browse files
fix bugs with --skip, implement --until
parent
6218b344
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/flac/decode.c
View file @
b04ce04d
...
...
@@ -49,6 +49,7 @@ typedef struct {
FLAC__bool
analysis_mode
;
analysis_options
aopts
;
utils__SkipUntilSpecification
*
skip_specification
;
utils__SkipUntilSpecification
*
until_specification
;
/* a canonicalized value of 0 mean end-of-stream (i.e. --until=-0) */
const
char
*
inbasefilename
;
const
char
*
outfilename
;
...
...
@@ -94,12 +95,13 @@ static FLAC__bool is_big_endian_host_;
/*
* local routines
*/
static
FLAC__bool
DecoderSession_construct
(
DecoderSession
*
d
,
FLAC__bool
is_ogg
,
FLAC__bool
verbose
,
FLAC__bool
is_wave_out
,
FLAC__bool
continue_through_decode_errors
,
FLAC__bool
analysis_mode
,
analysis_options
aopts
,
utils__SkipUntilSpecification
*
skip_specification
,
const
char
*
infilename
,
const
char
*
outfilename
);
static
FLAC__bool
DecoderSession_construct
(
DecoderSession
*
d
,
FLAC__bool
is_ogg
,
FLAC__bool
verbose
,
FLAC__bool
is_wave_out
,
FLAC__bool
continue_through_decode_errors
,
FLAC__bool
analysis_mode
,
analysis_options
aopts
,
utils__SkipUntilSpecification
*
skip_specification
,
utils__SkipUntilSpecification
*
until_specification
,
const
char
*
infilename
,
const
char
*
outfilename
);
static
void
DecoderSession_destroy
(
DecoderSession
*
d
,
FLAC__bool
error_occurred
);
static
FLAC__bool
DecoderSession_init_decoder
(
DecoderSession
*
d
,
decode_options_t
decode_options
,
const
char
*
infilename
);
static
FLAC__bool
DecoderSession_process
(
DecoderSession
*
d
);
static
int
DecoderSession_finish_ok
(
DecoderSession
*
d
);
static
int
DecoderSession_finish_error
(
DecoderSession
*
d
);
static
FLAC__bool
canonicalize_until_specification
(
utils__SkipUntilSpecification
*
spec
,
const
char
*
inbasefilename
,
unsigned
sample_rate
,
FLAC__uint64
skip
,
FLAC__uint64
total_samples_in_input
);
static
FLAC__bool
write_little_endian_uint16
(
FILE
*
f
,
FLAC__uint16
val
);
static
FLAC__bool
write_little_endian_uint32
(
FILE
*
f
,
FLAC__uint32
val
);
static
FLAC__bool
fixup_wave_chunk_size
(
const
char
*
outfilename
,
unsigned
riff_offset
,
unsigned
data_offset
,
FLAC__uint32
data_size
);
...
...
@@ -139,6 +141,7 @@ int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool
analysis_mode
,
aopts
,
&
options
.
common
.
skip_specification
,
&
options
.
common
.
until_specification
,
infilename
,
outfilename
)
...
...
@@ -175,6 +178,7 @@ int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool
analysis_mode
,
aopts
,
&
options
.
common
.
skip_specification
,
&
options
.
common
.
until_specification
,
infilename
,
outfilename
)
...
...
@@ -190,7 +194,7 @@ int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool
return
DecoderSession_finish_ok
(
&
decoder_session
);
}
FLAC__bool
DecoderSession_construct
(
DecoderSession
*
d
,
FLAC__bool
is_ogg
,
FLAC__bool
verbose
,
FLAC__bool
is_wave_out
,
FLAC__bool
continue_through_decode_errors
,
FLAC__bool
analysis_mode
,
analysis_options
aopts
,
utils__SkipUntilSpecification
*
skip_specification
,
const
char
*
infilename
,
const
char
*
outfilename
)
FLAC__bool
DecoderSession_construct
(
DecoderSession
*
d
,
FLAC__bool
is_ogg
,
FLAC__bool
verbose
,
FLAC__bool
is_wave_out
,
FLAC__bool
continue_through_decode_errors
,
FLAC__bool
analysis_mode
,
analysis_options
aopts
,
utils__SkipUntilSpecification
*
skip_specification
,
utils__SkipUntilSpecification
*
until_specification
,
const
char
*
infilename
,
const
char
*
outfilename
)
{
#ifdef FLAC__HAS_OGG
d
->
is_ogg
=
is_ogg
;
...
...
@@ -205,6 +209,7 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__
d
->
analysis_mode
=
analysis_mode
;
d
->
aopts
=
aopts
;
d
->
skip_specification
=
skip_specification
;
d
->
until_specification
=
until_specification
;
d
->
inbasefilename
=
grabbag__file_get_basename
(
infilename
);
d
->
outfilename
=
outfilename
;
...
...
@@ -489,6 +494,51 @@ int DecoderSession_finish_error(DecoderSession *d)
return
1
;
}
FLAC__bool
canonicalize_until_specification
(
utils__SkipUntilSpecification
*
spec
,
const
char
*
inbasefilename
,
unsigned
sample_rate
,
FLAC__uint64
skip
,
FLAC__uint64
total_samples_in_input
)
{
/* convert from mm:ss.sss to sample number if necessary */
flac__utils_canonicalize_skip_until_specification
(
spec
,
sample_rate
);
/* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */
if
(
spec
->
is_relative
&&
spec
->
value
.
samples
==
0
)
{
spec
->
is_relative
=
false
;
return
true
;
}
/* in any other case the total samples in the input must be known */
if
(
total_samples_in_input
==
0
)
{
fprintf
(
stderr
,
"%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0
\n
"
,
inbasefilename
);
return
false
;
}
FLAC__ASSERT
(
spec
->
value_is_samples
);
/* convert relative specifications to absolute */
if
(
spec
->
is_relative
)
{
if
(
spec
->
value
.
samples
<=
0
)
spec
->
value
.
samples
+=
(
FLAC__int64
)
total_samples_in_input
;
else
spec
->
value
.
samples
+=
skip
;
spec
->
is_relative
=
false
;
}
/* error check */
if
(
spec
->
value
.
samples
<
0
)
{
fprintf
(
stderr
,
"%s: ERROR, --until value is before beginning of input
\n
"
,
inbasefilename
);
return
false
;
}
if
((
FLAC__uint64
)
spec
->
value
.
samples
<=
skip
)
{
fprintf
(
stderr
,
"%s: ERROR, --until value is before --skip point
\n
"
,
inbasefilename
);
return
false
;
}
if
((
FLAC__uint64
)
spec
->
value
.
samples
>
total_samples_in_input
)
{
fprintf
(
stderr
,
"%s: ERROR, --until value is after end of input
\n
"
,
inbasefilename
);
return
false
;
}
return
true
;
}
FLAC__bool
write_little_endian_uint16
(
FILE
*
f
,
FLAC__uint16
val
)
{
FLAC__byte
*
b
=
(
FLAC__byte
*
)(
&
val
);
...
...
@@ -600,101 +650,119 @@ FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__F
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
decoder_session
->
samples_processed
+=
wide_samples
;
decoder_session
->
frame_counter
++
;
/*
* limit the number of samples to accept based on --until
*/
FLAC__ASSERT
(
!
decoder_session
->
skip_specification
->
is_relative
);
FLAC__ASSERT
(
decoder_session
->
skip_specification
->
value
.
samples
>=
0
);
FLAC__ASSERT
(
!
decoder_session
->
until_specification
->
is_relative
);
FLAC__ASSERT
(
decoder_session
->
until_specification
->
value
.
samples
>=
0
);
if
(
decoder_session
->
until_specification
->
value
.
samples
>
0
)
{
const
FLAC__uint64
skip
=
(
FLAC__uint64
)
decoder_session
->
skip_specification
->
value
.
samples
;
const
FLAC__uint64
until
=
(
FLAC__uint64
)
decoder_session
->
until_specification
->
value
.
samples
;
const
FLAC__uint64
input_samples_passed
=
skip
+
decoder_session
->
samples_processed
;
FLAC__ASSERT
(
until
>=
input_samples_passed
);
if
(
input_samples_passed
+
wide_samples
>
until
)
wide_samples
=
until
-
input_samples_passed
;
}
if
(
decoder_session
->
verbose
&&
!
(
decoder_session
->
frame_counter
&
0x3f
))
print_stats
(
decoder_session
);
if
(
wide_samples
>
0
)
{
decoder_session
->
samples_processed
+=
wide_samples
;
decoder_session
->
frame_counter
++
;
if
(
decoder_session
->
analysis_mode
)
{
flac__analyze_frame
(
frame
,
decoder_session
->
frame_counter
-
1
,
decoder_session
->
aopts
,
fout
);
}
else
if
(
!
decoder_session
->
test_only
)
{
if
(
bps
==
8
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u8buffer
[
sample
]
=
(
FLAC__uint8
)(
buffer
[
channel
][
wide_sample
]
+
0x80
);
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s8buffer
[
sample
]
=
(
FLAC__int8
)(
buffer
[
channel
][
wide_sample
]);
}
if
(
fwrite
(
u8buffer
,
1
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
else
if
(
bps
==
16
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u16buffer
[
sample
]
=
(
FLAC__uint16
)(
buffer
[
channel
][
wide_sample
]
+
0x8000
);
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s16buffer
[
sample
]
=
(
FLAC__int16
)(
buffer
[
channel
][
wide_sample
]);
}
if
(
is_big_endian
!=
is_big_endian_host_
)
{
unsigned
char
tmp
;
const
unsigned
bytes
=
sample
*
2
;
for
(
byte
=
0
;
byte
<
bytes
;
byte
+=
2
)
{
tmp
=
u8buffer
[
byte
];
u8buffer
[
byte
]
=
u8buffer
[
byte
+
1
];
u8buffer
[
byte
+
1
]
=
tmp
;
if
(
decoder_session
->
verbose
&&
!
(
decoder_session
->
frame_counter
&
0x3f
))
print_stats
(
decoder_session
);
if
(
decoder_session
->
analysis_mode
)
{
flac__analyze_frame
(
frame
,
decoder_session
->
frame_counter
-
1
,
decoder_session
->
aopts
,
fout
);
}
else
if
(
!
decoder_session
->
test_only
)
{
if
(
bps
==
8
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u8buffer
[
sample
]
=
(
FLAC__uint8
)(
buffer
[
channel
][
wide_sample
]
+
0x80
);
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s8buffer
[
sample
]
=
(
FLAC__int8
)(
buffer
[
channel
][
wide_sample
]);
}
if
(
fwrite
(
u8buffer
,
1
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
if
(
fwrite
(
u16buffer
,
2
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
else
if
(
bps
==
24
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u32buffer
[
sample
]
=
buffer
[
channel
][
wide_sample
]
+
0x800000
;
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s32buffer
[
sample
]
=
buffer
[
channel
][
wide_sample
];
}
if
(
is_big_endian
!=
is_big_endian_host_
)
{
unsigned
char
tmp
;
const
unsigned
bytes
=
sample
*
4
;
for
(
byte
=
0
;
byte
<
bytes
;
byte
+=
4
)
{
tmp
=
u8buffer
[
byte
];
u8buffer
[
byte
]
=
u8buffer
[
byte
+
3
];
u8buffer
[
byte
+
3
]
=
tmp
;
tmp
=
u8buffer
[
byte
+
1
];
u8buffer
[
byte
+
1
]
=
u8buffer
[
byte
+
2
];
u8buffer
[
byte
+
2
]
=
tmp
;
else
if
(
bps
==
16
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u16buffer
[
sample
]
=
(
FLAC__uint16
)(
buffer
[
channel
][
wide_sample
]
+
0x8000
);
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s16buffer
[
sample
]
=
(
FLAC__int16
)(
buffer
[
channel
][
wide_sample
]);
}
if
(
is_big_endian
!=
is_big_endian_host_
)
{
unsigned
char
tmp
;
const
unsigned
bytes
=
sample
*
2
;
for
(
byte
=
0
;
byte
<
bytes
;
byte
+=
2
)
{
tmp
=
u8buffer
[
byte
];
u8buffer
[
byte
]
=
u8buffer
[
byte
+
1
];
u8buffer
[
byte
+
1
]
=
tmp
;
}
}
if
(
fwrite
(
u16buffer
,
2
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
if
(
is_big_endian
)
{
unsigned
lbyte
;
const
unsigned
bytes
=
sample
*
4
;
for
(
lbyte
=
byte
=
0
;
byte
<
bytes
;
)
{
byte
++
;
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
else
if
(
bps
==
24
)
{
if
(
is_unsigned_samples
)
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
u32buffer
[
sample
]
=
buffer
[
channel
][
wide_sample
]
+
0x800000
;
}
else
{
for
(
sample
=
wide_sample
=
0
;
wide_sample
<
wide_samples
;
wide_sample
++
)
for
(
channel
=
0
;
channel
<
channels
;
channel
++
,
sample
++
)
s32buffer
[
sample
]
=
buffer
[
channel
][
wide_sample
];
}
if
(
is_big_endian
!=
is_big_endian_host_
)
{
unsigned
char
tmp
;
const
unsigned
bytes
=
sample
*
4
;
for
(
byte
=
0
;
byte
<
bytes
;
byte
+=
4
)
{
tmp
=
u8buffer
[
byte
];
u8buffer
[
byte
]
=
u8buffer
[
byte
+
3
];
u8buffer
[
byte
+
3
]
=
tmp
;
tmp
=
u8buffer
[
byte
+
1
];
u8buffer
[
byte
+
1
]
=
u8buffer
[
byte
+
2
];
u8buffer
[
byte
+
2
]
=
tmp
;
}
}
if
(
is_big_endian
)
{
unsigned
lbyte
;
const
unsigned
bytes
=
sample
*
4
;
for
(
lbyte
=
byte
=
0
;
byte
<
bytes
;
)
{
byte
++
;
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
}
}
else
{
unsigned
lbyte
;
const
unsigned
bytes
=
sample
*
4
;
for
(
lbyte
=
byte
=
0
;
byte
<
bytes
;
)
{
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
byte
++
;
}
}
if
(
fwrite
(
u8buffer
,
3
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
else
{
unsigned
lbyte
;
const
unsigned
bytes
=
sample
*
4
;
for
(
lbyte
=
byte
=
0
;
byte
<
bytes
;
)
{
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
u8buffer
[
lbyte
++
]
=
u8buffer
[
byte
++
];
byte
++
;
}
FLAC__ASSERT
(
0
);
}
if
(
fwrite
(
u8buffer
,
3
,
sample
,
fout
)
!=
sample
)
return
FLAC__STREAM_DECODER_WRITE_STATUS_ABORT
;
}
else
{
FLAC__ASSERT
(
0
);
}
}
return
FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE
;
...
...
@@ -705,7 +773,7 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata
DecoderSession
*
decoder_session
=
(
DecoderSession
*
)
client_data
;
(
void
)
decoder
;
if
(
metadata
->
type
==
FLAC__METADATA_TYPE_STREAMINFO
)
{
FLAC__uint64
skip
;
FLAC__uint64
skip
,
until
;
decoder_session
->
bps
=
metadata
->
data
.
stream_info
.
bits_per_sample
;
decoder_session
->
channels
=
metadata
->
data
.
stream_info
.
channels
;
decoder_session
->
sample_rate
=
metadata
->
data
.
stream_info
.
sample_rate
;
...
...
@@ -716,17 +784,26 @@ void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata
/* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
if
(
metadata
->
data
.
stream_info
.
total_samples
>
0
&&
skip
>=
metadata
->
data
.
stream_info
.
total_samples
)
{
fprintf
(
stderr
,
"%s: ERROR trying to skip more samples than in stream
\n
"
,
decoder_session
->
inbasefilename
);
fprintf
(
stderr
,
"%s: ERROR trying to
--
skip more samples than in stream
\n
"
,
decoder_session
->
inbasefilename
);
decoder_session
->
abort_flag
=
true
;
return
;
}
else
if
(
metadata
->
data
.
stream_info
.
total_samples
==
0
&&
skip
>
0
)
{
fprintf
(
stderr
,
"%s: ERROR, can't skip when FLAC metadata has total sample count of 0
\n
"
,
decoder_session
->
inbasefilename
);
fprintf
(
stderr
,
"%s: ERROR, can't
--
skip when FLAC metadata has total sample count of 0
\n
"
,
decoder_session
->
inbasefilename
);
decoder_session
->
abort_flag
=
true
;
return
;
}
else
decoder_session
->
total_samples
=
metadata
->
data
.
stream_info
.
total_samples
-
skip
;
decoder_session
->
total_samples
=
metadata
->
data
.
stream_info
.
total_samples
-
skip
;
/* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */
if
(
!
canonicalize_until_specification
(
decoder_session
->
until_specification
,
decoder_session
->
inbasefilename
,
decoder_session
->
sample_rate
,
skip
,
metadata
->
data
.
stream_info
.
total_samples
))
{
decoder_session
->
abort_flag
=
true
;
return
;
}
FLAC__ASSERT
(
decoder_session
->
until_specification
->
value
.
samples
>=
0
);
until
=
(
FLAC__uint64
)
decoder_session
->
until_specification
->
value
.
samples
;
decoder_session
->
total_samples
-=
(
metadata
->
data
.
stream_info
.
total_samples
-
until
);
if
(
decoder_session
->
bps
!=
8
&&
decoder_session
->
bps
!=
16
&&
decoder_session
->
bps
!=
24
)
{
fprintf
(
stderr
,
"%s: ERROR: bits per sample is not 8/16/24
\n
"
,
decoder_session
->
inbasefilename
);
...
...
src/flac/decode.h
View file @
b04ce04d
...
...
@@ -35,6 +35,7 @@ typedef struct {
long
serial_number
;
#endif
utils__SkipUntilSpecification
skip_specification
;
utils__SkipUntilSpecification
until_specification
;
}
decode_options_t
;
typedef
struct
{
...
...
src/flac/encode.c
View file @
b04ce04d
...
...
@@ -59,6 +59,7 @@ typedef struct {
const
char
*
outfilename
;
FLAC__uint64
skip
;
FLAC__uint64
until
;
/* a value of 0 mean end-of-stream (i.e. --until=-0) */
FLAC__bool
replay_gain
;
unsigned
channels
;
unsigned
bits_per_sample
;
...
...
@@ -127,6 +128,7 @@ static int EncoderSession_finish_error(EncoderSession *e);
static
FLAC__bool
EncoderSession_init_encoder
(
EncoderSession
*
e
,
encode_options_t
options
,
unsigned
channels
,
unsigned
bps
,
unsigned
sample_rate
);
static
FLAC__bool
EncoderSession_process
(
EncoderSession
*
e
,
const
FLAC__int32
*
const
buffer
[],
unsigned
samples
);
static
FLAC__bool
convert_to_seek_table_template
(
const
char
*
requested_seek_points
,
int
num_requested_seek_points
,
FLAC__StreamMetadata
*
cuesheet
,
EncoderSession
*
e
);
static
FLAC__bool
canonicalize_until_specification
(
utils__SkipUntilSpecification
*
spec
,
const
char
*
inbasefilename
,
unsigned
sample_rate
,
FLAC__uint64
skip
,
FLAC__uint64
total_samples_in_input
);
static
void
format_input
(
FLAC__int32
*
dest
[],
unsigned
wide_samples
,
FLAC__bool
is_big_endian
,
FLAC__bool
is_unsigned_samples
,
unsigned
channels
,
unsigned
bps
);
#ifdef FLAC__HAS_OGG
static
FLAC__StreamEncoderWriteStatus
ogg_stream_encoder_write_callback
(
const
OggFLAC__StreamEncoder
*
encoder
,
const
FLAC__byte
buffer
[],
unsigned
bytes
,
unsigned
samples
,
unsigned
current_frame
,
void
*
client_data
);
...
...
@@ -276,6 +278,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
else
if
(
got_ssnd_chunk
==
false
&&
!
strncmp
(
chunk_id
,
"SSND"
,
4
))
{
/* sound data chunk */
unsigned
int
offset
=
0U
,
block_size
=
0U
,
align_remainder
=
0U
,
data_bytes
;
size_t
bytes_per_frame
=
channels
*
(
bps
>>
3
);
FLAC__uint64
total_samples_in_input
;
FLAC__bool
pad
=
false
;
if
(
got_comm_chunk
==
false
)
{
...
...
@@ -292,6 +295,7 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
}
data_bytes
=
xx
;
pad
=
(
data_bytes
&
1U
)
?
true
:
false
;
data_bytes
-=
8U
;
/* offset */
if
(
!
read_big_endian_uint32
(
infile
,
&
xx
,
false
,
encoder_session
.
inbasefilename
))
...
...
@@ -311,6 +315,19 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
}
block_size
=
xx
;
/* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */
FLAC__ASSERT
(
options
.
common
.
sector_align
||
*
options
.
common
.
align_reservoir_samples
==
0
);
total_samples_in_input
=
data_bytes
/
bytes_per_frame
+
*
options
.
common
.
align_reservoir_samples
;
/*
* now that we know the input size, canonicalize the
* --until string to an absolute sample number:
*/
if
(
!
canonicalize_until_specification
(
&
options
.
common
.
until_specification
,
encoder_session
.
inbasefilename
,
sample_rate
,
encoder_session
.
skip
,
total_samples_in_input
))
return
EncoderSession_finish_error
(
&
encoder_session
);
encoder_session
.
until
=
(
FLAC__uint64
)
options
.
common
.
until_specification
.
value
.
samples
;
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
encoder_session
.
until
==
0
);
if
(
encoder_session
.
skip
>
0U
)
{
FLAC__uint64
remaining
=
encoder_session
.
skip
*
bytes_per_frame
;
...
...
@@ -332,8 +349,15 @@ flac__encode_aif(FILE *infile, long infilesize, const char *infilename, const ch
}
}
data_bytes
-=
(
8U
+
(
unsigned
int
)
encoder_session
.
skip
*
bytes_per_frame
);
/*@@@ WATCHOUT: 4GB limit */
encoder_session
.
total_samples_to_encode
=
data_bytes
/
bytes_per_frame
+
*
options
.
common
.
align_reservoir_samples
;
data_bytes
-=
(
unsigned
int
)
encoder_session
.
skip
*
bytes_per_frame
;
/*@@@ WATCHOUT: 4GB limit */
encoder_session
.
total_samples_to_encode
=
total_samples_in_input
-
encoder_session
.
skip
;
if
(
encoder_session
.
until
>
0
)
{
const
FLAC__uint64
trim
=
total_samples_in_input
-
encoder_session
.
until
;
FLAC__ASSERT
(
total_samples_in_input
>
0
);
FLAC__ASSERT
(
!
options
.
common
.
sector_align
);
data_bytes
-=
(
unsigned
int
)
trim
*
bytes_per_frame
;
encoder_session
.
total_samples_to_encode
-=
trim
;
}
if
(
options
.
common
.
sector_align
)
{
align_remainder
=
(
unsigned
int
)(
encoder_session
.
total_samples_to_encode
%
588U
);
if
(
options
.
common
.
is_last_file
)
...
...
@@ -613,6 +637,8 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
got_fmt_chunk
=
true
;
}
else
if
(
xx
==
0x61746164
&&
!
got_data_chunk
&&
got_fmt_chunk
)
{
/* "data" */
FLAC__uint64
total_samples_in_input
;
/* data size */
if
(
!
read_little_endian_uint32
(
infile
,
&
xx
,
false
,
encoder_session
.
inbasefilename
))
return
EncoderSession_finish_error
(
&
encoder_session
);
...
...
@@ -620,6 +646,19 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
bytes_per_wide_sample
=
channels
*
(
bps
>>
3
);
/* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */
FLAC__ASSERT
(
options
.
common
.
sector_align
||
*
options
.
common
.
align_reservoir_samples
==
0
);
total_samples_in_input
=
data_bytes
/
bytes_per_wide_sample
+
*
options
.
common
.
align_reservoir_samples
;
/*
* now that we know the input size, canonicalize the
* --until string to an absolute sample number:
*/
if
(
!
canonicalize_until_specification
(
&
options
.
common
.
until_specification
,
encoder_session
.
inbasefilename
,
sample_rate
,
encoder_session
.
skip
,
total_samples_in_input
))
return
EncoderSession_finish_error
(
&
encoder_session
);
encoder_session
.
until
=
(
FLAC__uint64
)
options
.
common
.
until_specification
.
value
.
samples
;
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
encoder_session
.
until
==
0
);
if
(
encoder_session
.
skip
>
0
)
{
if
(
fseek
(
infile
,
bytes_per_wide_sample
*
(
unsigned
)
encoder_session
.
skip
,
SEEK_CUR
)
<
0
)
{
/* can't seek input, read ahead manually... */
...
...
@@ -636,7 +675,14 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
}
data_bytes
-=
(
unsigned
)
encoder_session
.
skip
*
bytes_per_wide_sample
;
/*@@@ WATCHOUT: 4GB limit */
encoder_session
.
total_samples_to_encode
=
data_bytes
/
bytes_per_wide_sample
+
*
options
.
common
.
align_reservoir_samples
;
encoder_session
.
total_samples_to_encode
=
total_samples_in_input
-
encoder_session
.
skip
;
if
(
encoder_session
.
until
>
0
)
{
const
FLAC__uint64
trim
=
total_samples_in_input
-
encoder_session
.
until
;
FLAC__ASSERT
(
total_samples_in_input
>
0
);
FLAC__ASSERT
(
!
options
.
common
.
sector_align
);
data_bytes
-=
(
unsigned
int
)
trim
*
bytes_per_wide_sample
;
encoder_session
.
total_samples_to_encode
-=
trim
;
}
if
(
options
.
common
.
sector_align
)
{
align_remainder
=
(
unsigned
)(
encoder_session
.
total_samples_to_encode
%
588
);
if
(
options
.
common
.
is_last_file
)
...
...
@@ -797,6 +843,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
const
size_t
bytes_per_wide_sample
=
options
.
channels
*
(
options
.
bps
>>
3
);
unsigned
align_remainder
=
0
;
int
info_align_carry
=
-
1
,
info_align_zero
=
-
1
;
FLAC__uint64
total_samples_in_input
=
0
;;
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
options
.
channels
==
2
);
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
options
.
bps
==
16
);
...
...
@@ -830,28 +877,40 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
FLAC__ASSERT
(
options
.
common
.
skip_specification
.
value
.
samples
>=
0
);
encoder_session
.
skip
=
(
FLAC__uint64
)
options
.
common
.
skip_specification
.
value
.
samples
;
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
encoder_session
.
skip
==
0
);
FLAC__ASSERT
(
!
options
.
common
.
replay_gain
||
encoder_session
.
skip
==
0
);
/* get the file length */
if
(
infilesize
<
0
)
{
encoder_session
.
total_samples_to_encode
=
encoder_session
.
unencoded_size
=
0
;
}
if
(
infilesize
<
0
)
total_samples_in_input
=
0
;
else
{
if
(
options
.
common
.
sector_align
)
{
FLAC__ASSERT
(
encoder_session
.
skip
==
0
);
encoder_session
.
total_samples_to_encode
=
(
unsigned
)
infilesize
/
bytes_per_wide_sample
+
*
options
.
common
.
align_reservoir_samples
;
align_remainder
=
(
unsigned
)(
encoder_session
.
total_samples_to_encode
%
588
);
if
(
options
.
common
.
is_last_file
)
encoder_session
.
total_samples_to_encode
+=
(
588
-
align_remainder
);
/* will pad with zeroes */
else
encoder_session
.
total_samples_to_encode
-=
align_remainder
;
/* will stop short and carry over to next file */
}
else
{
encoder_session
.
total_samples_to_encode
=
(
unsigned
)
infilesize
/
bytes_per_wide_sample
-
encoder_session
.
skip
;
}
/* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */
FLAC__ASSERT
(
options
.
common
.
sector_align
||
*
options
.
common
.
align_reservoir_samples
==
0
);
total_samples_in_input
=
(
unsigned
)
infilesize
/
bytes_per_wide_sample
+
*
options
.
common
.
align_reservoir_samples
;
}
encoder_session
.
unencoded_size
=
encoder_session
.
total_samples_to_encode
*
bytes_per_wide_sample
;
/*
* now that we know the input size, canonicalize the
* --until strings to a number of samples:
*/
if
(
!
canonicalize_until_specification
(
&
options
.
common
.
until_specification
,
encoder_session
.
inbasefilename
,
options
.
sample_rate
,
encoder_session
.
skip
,
total_samples_in_input
))
return
EncoderSession_finish_error
(
&
encoder_session
);
encoder_session
.
until
=
(
FLAC__uint64
)
options
.
common
.
until_specification
.
value
.
samples
;
FLAC__ASSERT
(
!
options
.
common
.
sector_align
||
encoder_session
.
until
==
0
);
encoder_session
.
total_samples_to_encode
=
total_samples_in_input
-
encoder_session
.
skip
;
if
(
encoder_session
.
until
>
0
)
{
const
FLAC__uint64
trim
=
total_samples_in_input
-
encoder_session
.
until
;
FLAC__ASSERT
(
total_samples_in_input
>
0
);
FLAC__ASSERT
(
!
options
.
common
.
sector_align
);
encoder_session
.
total_samples_to_encode
-=
trim
;
}
if
(
infilesize
>=
0
&&
options
.
common
.
sector_align
)
{
FLAC__ASSERT
(
encoder_session
.
skip
==
0
);
align_remainder
=
(
unsigned
)(
encoder_session
.
total_samples_to_encode
%
588
);
if
(
options
.
common
.
is_last_file
)
encoder_session
.
total_samples_to_encode
+=
(
588
-
align_remainder
);
/* will pad with zeroes */
else
encoder_session
.
total_samples_to_encode
-=
align_remainder
;
/* will stop short and carry over to next file */
}
encoder_session
.
unencoded_size
=
encoder_session
.
total_samples_to_encode
*
bytes_per_wide_sample
;
if
(
encoder_session
.
verbose
&&
encoder_session
.
total_samples_to_encode
<=
0
)
fprintf
(
stderr
,
"(No runtime statistics possible; please wait for encoding to finish...)
\n
"
);
...
...
@@ -905,43 +964,94 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
else
{
*
options
.
common
.
align_reservoir_samples
=
align_remainder
;
infilesize
-=
(
long
)((
*
options
.
common
.
align_reservoir_samples
)
*
bytes_per_wide_sample
);
FLAC__ASSERT
(
infilesize
>=
0
);
}
}
/*
* now do from the file
*/
while
(
!
feof
(
infile
))
{
if
(
lookahead_length
>
0
)
{
FLAC__ASSERT
(
lookahead_length
<
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
);
memcpy
(
ucbuffer_
,
lookahead
,
lookahead_length
);
bytes_read
=
fread
(
ucbuffer_
+
lookahead_length
,
sizeof
(
unsigned
char
),
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
-
lookahead_length
,
infile
)
+
lookahead_length
;
if
(
ferror
(
infile
))
{
fprintf
(
stderr
,
"%s: ERROR during read
\n
"
,
encoder_session
.
inbasefilename
);
return
EncoderSession_finish_error
(
&
encoder_session
);
if
(
infilesize
<
0
)
{
while
(
!
feof
(
infile
))
{
if
(
lookahead_length
>
0
)
{
FLAC__ASSERT
(
lookahead_length
<
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
);
memcpy
(
ucbuffer_
,
lookahead
,
lookahead_length
);
bytes_read
=
fread
(
ucbuffer_
+
lookahead_length
,
sizeof
(
unsigned
char
),
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
-
lookahead_length
,
infile
)
+
lookahead_length
;
if
(
ferror
(
infile
))
{
fprintf
(
stderr
,
"%s: ERROR during read
\n
"
,
encoder_session
.
inbasefilename
);
return
EncoderSession_finish_error
(
&
encoder_session
);
}
lookahead_length
=
0
;
}
lookahead_length
=
0
;
}
else
bytes_read
=
fread
(
ucbuffer_
,
sizeof
(
unsigned
char
),
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
,
infile
);
else
bytes_read
=
fread
(
ucbuffer_
,
sizeof
(
unsigned
char
),
CHUNK_OF_SAMPLES
*
bytes_per_wide_sample
,
infile
);
if
(
bytes_read
==
0
)
{
if
(
ferror
(
infile
))
{
fprintf
(
stderr
,
"%s: ERROR during read
\n
"
,
encoder_session
.
inbasefilename
);
if
(
bytes_read
==
0
)
{
if
(
ferror
(
infile
))
{
fprintf
(
stderr
,
"%s: ERROR during read
\n
"
,
encoder_session
.
inbasefilename
);
return
EncoderSession_finish_error
(
&
encoder_session
);
}
}
else
if
(
bytes_read
%
bytes_per_wide_sample
!=
0
)
{
fprintf
(
stderr
,
"%s: ERROR: got partial sample
\n
"
,
encoder_session
.
inbasefilename
);
return
EncoderSession_finish_error
(
&
encoder_session
);
}
else
{
unsigned
wide_samples
=
bytes_read
/
bytes_per_wide_sample
;
format_input
(
input_
,
wide_samples
,
options
.
is_big_endian
,
options
.
is_unsigned_samples
,
options
.
channels
,
options
.
bps
);
if
(
!
EncoderSession_process
(
&
encoder_session
,
(
const
FLAC__int32
*
const
*
)
input_
,
wide_samples
))
{
print_error_with_state
(
&
encoder_session
,
"ERROR during encoding"
);
return
EncoderSession_finish_error
(
&
encoder_session
);
}
}
}
else
if
(
bytes_read
%
bytes_per_wide_sample
!=