1
0
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:
thor
2013-03-17 14:01:07 +00:00
parent d5468c6fbe
commit c7a42a0f2c
4 changed files with 43 additions and 12 deletions

5
NEWS
View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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.");