mirror of
http://mpg123.de/trunk/.git
synced 2025-10-25 04:37:34 +03:00
Another go at the wretched WAV writing.
git-svn-id: svn://scm.orgis.org/mpg123/trunk@3296 35dc7657-300d-0410-a2e5-dc2837fedb53
This commit is contained in:
5
NEWS
5
NEWS
@@ -1,3 +1,8 @@
|
||||
1.16.0
|
||||
---
|
||||
- upcoming: kickass optimizations by Taihei
|
||||
- Fix WAV writing. AGAIN. People love to decode WAV to stdout in various ways that started to get broken with me starting to care for people who like to write to full disks. I frikkin' HATE this rat race! I'm even starting to SHOUT. Now, the code prefers to write no header at all (when there is no actual output) instead of possibly writing too many misleading ones. Getting the blame for breaking dir2ogg repeatedly while trying to cope with one fatal situation that you cannot really cope with sucks. Big time. I hope that's it now!
|
||||
|
||||
1.15.2
|
||||
---
|
||||
- build fix with older shells (== in configure)
|
||||
|
||||
@@ -8,7 +8,7 @@ dnl Require autoconf version >= 2.57
|
||||
AC_PREREQ(2.57)
|
||||
|
||||
dnl ############# Initialisation
|
||||
AC_INIT([mpg123], [1.15.2], [mpg123-devel@lists.sourceforge.net])
|
||||
AC_INIT([mpg123], [1.16.0], [mpg123-devel@lists.sourceforge.net])
|
||||
dnl Increment API_VERSION when the API gets changes (new functions).
|
||||
API_VERSION=37
|
||||
LIB_PATCHLEVEL=1
|
||||
|
||||
@@ -176,13 +176,13 @@ is used as file name. You can also use
|
||||
.I --au
|
||||
and
|
||||
.I --cdr
|
||||
for AU and CDR format, respectively.
|
||||
for AU and CDR format, respectively. Note that WAV/AU writing to non-seekable files, or redirected stdout, needs some thought. Since 1.16.0, the logic changed to writing the header with the first actual data. This avoids spurious WAV headers in a pipe, for example. The result of decoding nothing to WAV/AU is a file consisting just of the header when it is seekable and really nothing when not (not even a header). Correctly writing data with prophetic headers to stdout is no easy business.
|
||||
.TP
|
||||
\fB\-\^\-au \fIfile
|
||||
Does not play the MPEG file but writes it to
|
||||
.I file
|
||||
in SUN audio format. If \- is used as the filename, the AU file is
|
||||
written to stdout.
|
||||
written to stdout. See paragraph about WAV writing for header fun with non-seekable streams.
|
||||
.TP
|
||||
\fB\-\^\-cdr \fIfile
|
||||
Does not play the MPEG file but writes it to
|
||||
|
||||
42
src/wav.c
42
src/wav.c
@@ -58,6 +58,13 @@ static int flipendian=0;
|
||||
int bytes_per_sample = -1;
|
||||
int floatwav = 0; /* If we write a floating point WAV file. */
|
||||
|
||||
/* Open routines only prepare a header, stored here and written on first actual
|
||||
data write. If no data is written at all, proper files will still get a
|
||||
header via the update at closing; non-seekable streams will just have no
|
||||
no header if there is no data. */
|
||||
void *the_header = NULL;
|
||||
size_t the_header_size = 0;
|
||||
|
||||
/* Convertfunctions: */
|
||||
/* always little endian */
|
||||
|
||||
@@ -114,6 +121,10 @@ static int open_file(char *filename)
|
||||
#endif
|
||||
if(!strcmp("-",filename)) {
|
||||
wavfp = stdout;
|
||||
/* If stdout is redirected to a file, seeks suddenly can work.
|
||||
Doing one here to ensure that such a file has the same output
|
||||
it had when opening directly as such. */
|
||||
fseek(wavfp, 0L, SEEK_SET);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
@@ -152,7 +163,6 @@ static int close_file()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wrapper over header writing; ensure that stdout doesn't get multiple headers. */
|
||||
static int write_header(const void*ptr, size_t size)
|
||||
{
|
||||
if(fwrite(ptr, size, 1, wavfp) != 1 || fflush(wavfp))
|
||||
@@ -206,7 +216,10 @@ int au_open(audio_output_t *ao)
|
||||
|
||||
datalen = 0;
|
||||
|
||||
return write_header(&auhead, sizeof(auhead));
|
||||
the_header = &auhead;
|
||||
the_header_size = sizeof(auhead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cdr_open(audio_output_t *ao)
|
||||
@@ -229,6 +242,9 @@ int cdr_open(audio_output_t *ao)
|
||||
if(open_file(ao->device) < 0)
|
||||
return -1;
|
||||
|
||||
the_header = NULL;
|
||||
the_header_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -306,10 +322,15 @@ int wav_open(audio_output_t *ao)
|
||||
long2littleendian(datalen+sizeof(RIFF.WAVE),RIFF.WAVElen,sizeof(RIFF.WAVElen));
|
||||
}
|
||||
|
||||
if(!( ( floatwav && !write_header(&RIFF_FLOAT, sizeof(RIFF_FLOAT)))
|
||||
|| (!floatwav && !write_header(&RIFF, sizeof(RIFF))) ))
|
||||
if(floatwav)
|
||||
{
|
||||
return -1;
|
||||
the_header = &RIFF_FLOAT;
|
||||
the_header_size = sizeof(RIFF_FLOAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
the_header = &RIFF;
|
||||
the_header_size = sizeof(RIFF);
|
||||
}
|
||||
|
||||
datalen = 0;
|
||||
@@ -326,6 +347,11 @@ int wav_write(unsigned char *buf,int len)
|
||||
if(!wavfp)
|
||||
return 0;
|
||||
|
||||
if(datalen == 0)
|
||||
{
|
||||
if(write_header(the_header, the_header_size) < 0) return 0;
|
||||
}
|
||||
|
||||
if(flipendian)
|
||||
{
|
||||
if(bytes_per_sample == 4) /* 32 bit */
|
||||
@@ -396,14 +422,14 @@ int wav_close(void)
|
||||
long2littleendian(datalen/(from_little(RIFF_FLOAT.WAVE.fmt.Channels,2)*from_little(RIFF_FLOAT.WAVE.fmt.BitsPerSample,2)/8),
|
||||
RIFF_FLOAT.WAVE.fact.samplelen,sizeof(RIFF_FLOAT.WAVE.fact.samplelen));
|
||||
/* Always (over)writing the header here; also for stdout, when fseek worked, this overwrite works. */
|
||||
fwrite(&RIFF_FLOAT, sizeof(RIFF_FLOAT),1,wavfp);
|
||||
write_header(&RIFF_FLOAT, sizeof(RIFF_FLOAT));
|
||||
}
|
||||
else
|
||||
{
|
||||
long2littleendian(datalen,RIFF.WAVE.data.datalen,sizeof(RIFF.WAVE.data.datalen));
|
||||
long2littleendian(datalen+sizeof(RIFF.WAVE),RIFF.WAVElen,sizeof(RIFF.WAVElen));
|
||||
/* Always (over)writing the header here; also for stdout, when fseek worked, this overwrite works. */
|
||||
fwrite(&RIFF, sizeof(RIFF),1,wavfp);
|
||||
write_header(&RIFF, sizeof(RIFF));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -427,7 +453,7 @@ int au_close(void)
|
||||
if(fseek(wavfp, 0L, SEEK_SET) >= 0) {
|
||||
long2bigendian(datalen,auhead.datalen,sizeof(auhead.datalen));
|
||||
/* Always (over)writing the header here; also for stdout, when fseek worked, this overwrite works. */
|
||||
fwrite(&auhead, sizeof(auhead),1,wavfp);
|
||||
write_header(&auhead, sizeof(auhead));
|
||||
}
|
||||
else
|
||||
warning("Cannot rewind AU file. File-format isn't fully conform now.");
|
||||
|
||||
Reference in New Issue
Block a user