[alsa-devel] [PATCH] aplay: Fix header for raw format
Daniel Baluta
daniel.baluta at gmail.com
Mon Jul 3 11:41:44 CEST 2017
On Fri, Jun 30, 2017 at 5:20 PM, Takashi Iwai <tiwai at suse.de> wrote:
> On Fri, 30 Jun 2017 15:11:38 +0200,
> Daniel Baluta wrote:
>>
>> Hi Takashi,
>>
>> Thanks a lot for your feedback.
>>
>> On Fri, Jun 30, 2017 at 9:54 AM, Takashi Iwai <tiwai at suse.de> wrote:
>> > On Thu, 29 Jun 2017 13:17:16 +0200,
>> > Ion-Horia Petrisor wrote:
>> >>
>> >> Raw format has no header, so use 0 when calling playback_go.
>> >
>> > It's the value passed for the length that has been already loaded.
>> > The program has read dta bytes for parsing the header, and it's raw
>> > data without header. Thus you need to pass dta there.
>> >
>> With the current code we assume that the raw files have at least 26 bytes.
>> (sizeof (VocHeader).
>>
>> I think it doesn't matter here that dta bytes has already been loaded. These
>> bytes useful to figure out the file header type.
>>
>> To keep things simple we can assume that in the case of raw files there is no
>> header, so second parameter of playback_go (named loaded) can be set to 0.
>
> The loaded parameter of playback_go() doesn't mean that. It's the
> size that has been already read onto the audio buffer. If you pass 0
> there, it means that you discard the first 26 bytes samples you have
> already read without playing.
Agree. Passing 0 discards the first 26 bytes that have already been read
but these bytes will be re-read inside playback_go so they will be played.
playback_go( .. loaded = 0)
..
r = safe_read(fd, audio_buf + loaded, c). [aplay.c: 2757]
>
>> The worst things that can happen is that we re-read the first 26 bytes
>> (previously
>> read as VoC header).
>
> Where is re-read...?
As explained above, we first read the header [be it .au, .voc or .wav] in
playback() function and then because we pass [with our proposed patch
loaded = 0]
we re-read those bytes in playback_go function.
Of course, is not optimal. Let me look at your patch.
>
>> We are trying to introduce a new parameter --samples which tells aplay to only
>> playback/record s number of samples.
>>
>> We modified calc_count() accordingly so that when receives the
>> --samples parameter
>> computes the correct number of bytes to be read.
>>
>> Anyhow, it doesn't work as expected because aplay expects files to have at least
>> 26 bytes.
>>
>> The correct solution would be that in the case of raw files not assume
>> any header
>> and read samples * sample_size bytes from the beginning of the file.
>
> I see now what you want, but the patch is incorrect.
> I guess a patch something like below is what you want.
>
>
> thanks,
>
> Takashi
>
> ---
> diff --git a/aplay/aplay.c b/aplay/aplay.c
> index 00af66246cad..a902be5cf9cb 100644
> --- a/aplay/aplay.c
> +++ b/aplay/aplay.c
> @@ -2782,12 +2782,65 @@ static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *n
> * let's play or capture it (capture_type says VOC/WAVE/raw)
> */
>
> -static void playback(char *name)
> +static void read_header(int *loaded, int header_size)
> +{
> + if (*loaded < header_size) {
> + header_size -= *loaded;
> + if (safe_read(fd, audiobuf, header_size) != header_size) {
audio_buf + *loaded here.
> + error(_("read error"));
> + prg_exit(EXIT_FAILURE);
> + }
> + *loaded += header_size;
> + }
> +}
> +
> +static int playback_au(char *name, int *loaded)
> +{
> + read_header(loaded, sizeof(AuHeader));
> + if (test_au(fd, audiobuf) < 0)
> + return -1;
> + rhwparams.format = hwparams.format;
> + pbrec_count = calc_count();
> + playback_go(fd, *loaded - sizeof(AuHeader), pbrec_count, FORMAT_AU, name);
> + return 0;
> +}
> +
> +static int playback_voc(char *name, int *loaded)
> {
> int ofs;
> - size_t dta;
> +
> + read_header(loaded, sizeof(VocHeader));
> + if ((ofs = test_vocfile(audiobuf)) < 0)
> + return -1;
> + pbrec_count = calc_count();
> + voc_play(fd, ofs, name);
> + return 0;
> +}
> +
> +static int playback_wave(char *name, int *loaded)
> +{
> ssize_t dtawave;
>
> + read_header(loaded, sizeof(WaveHeader));
> + if ((dtawave = test_wavefile(fd, audiobuf, *loaded)) < 0)
> + return -1;
> + pbrec_count = calc_count();
> + playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name);
> + return 0;
> +}
> +
> +static int playback_raw(char *name, int *loaded)
> +{
> + init_raw_data();
> + pbrec_count = calc_count();
> + playback_go(fd, *loaded, pbrec_count, FORMAT_RAW, name);
> + return 0;
> +}
> +
> +static void playback(char *name)
> +{
> + int loaded = 0;
> +
> pbrec_count = LLONG_MAX;
> fdcount = 0;
> if (!name || !strcmp(name, "-")) {
> @@ -2800,40 +2853,29 @@ static void playback(char *name)
> prg_exit(EXIT_FAILURE);
> }
> }
> - /* read the file header */
> - dta = sizeof(AuHeader);
> - if ((size_t)safe_read(fd, audiobuf, dta) != dta) {
> - error(_("read error"));
> - prg_exit(EXIT_FAILURE);
> - }
> - if (test_au(fd, audiobuf) >= 0) {
> - rhwparams.format = hwparams.format;
> - pbrec_count = calc_count();
> - playback_go(fd, 0, pbrec_count, FORMAT_AU, name);
> - goto __end;
> - }
> - dta = sizeof(VocHeader);
> - if ((size_t)safe_read(fd, audiobuf + sizeof(AuHeader),
> - dta - sizeof(AuHeader)) != dta - sizeof(AuHeader)) {
> - error(_("read error"));
> - prg_exit(EXIT_FAILURE);;
> - }
> - if ((ofs = test_vocfile(audiobuf)) >= 0) {
> - pbrec_count = calc_count();
> - voc_play(fd, ofs, name);
> - goto __end;
> - }
> - /* read bytes for WAVE-header */
> - if ((dtawave = test_wavefile(fd, audiobuf, dta)) >= 0) {
> - pbrec_count = calc_count();
> - playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name);
> - } else {
> - /* should be raw data */
> - init_raw_data();
> - pbrec_count = calc_count();
> - playback_go(fd, dta, pbrec_count, FORMAT_RAW, name);
> +
> + switch (file_type) {
> + case FORMAT_AU:
> + playback_au(name, &loaded);
> + break;
> + case FORMAT_VOC:
> + playback_voc(name, &loaded);
> + break;
> + case FORMAT_WAVE:
> + playback_wave(name, &loaded);
> + break;
> + case FORMAT_RAW:
> + playback_raw(name, &loaded);
> + break;
> + default:
> + /* parse the file header */
> + if (playback_au(name, &loaded) < 0 &&
> + playback_voc(name, &loaded) < 0 &&
> + playback_wave(name, &loaded) < 0)
> + playback_raw(name, &loaded); /* should be raw data */
> + break;
> }
> - __end:
> +
> if (fd != 0)
> close(fd);
> }
This is more elegant and also fixes our problem. Care to send a formal patch?
thanks,
daniel.
More information about the Alsa-devel
mailing list