diff options
Diffstat (limited to 'recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch')
-rwxr-xr-x | recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch b/recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch new file mode 100755 index 00000000..9189bc0e --- /dev/null +++ b/recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch | |||
@@ -0,0 +1,221 @@ | |||
1 | From 4d4bc0a958fe254531920095fbabc241aad88113 Mon Sep 17 00:00:00 2001 | ||
2 | From: Shengjiu Wang <shengjiu.wang@nxp.com> | ||
3 | Date: Tue, 28 Jul 2020 13:00:36 +0800 | ||
4 | Subject: [PATCH] cplay: Support wave file | ||
5 | |||
6 | The supported format is mono/stereo, S16_LE/S32_LE, 8kHz-192kHz. | ||
7 | Command is: | ||
8 | cplay -c x -I PCM test.wav | ||
9 | |||
10 | Upstream-Status: Inappropriate [i.MX specific] | ||
11 | Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> | ||
12 | --- | ||
13 | include/tinycompress/wave_formats.h | 51 +++++++++++++ | ||
14 | src/utils/cplay.c | 107 ++++++++++++++++++++++++++++ | ||
15 | 2 files changed, 158 insertions(+) | ||
16 | create mode 100644 include/tinycompress/wave_formats.h | ||
17 | |||
18 | diff --git a/include/tinycompress/wave_formats.h b/include/tinycompress/wave_formats.h | ||
19 | new file mode 100644 | ||
20 | index 000000000000..4e2e009206cf | ||
21 | --- /dev/null | ||
22 | +++ b/include/tinycompress/wave_formats.h | ||
23 | @@ -0,0 +1,51 @@ | ||
24 | +#ifndef WAVE_FORMATS_H | ||
25 | +#define WAVE_FORMATS_H 1 | ||
26 | + | ||
27 | +#define COMPOSE_ID(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) | ||
28 | + | ||
29 | +#define WAV_RIFF COMPOSE_ID('R','I','F','F') | ||
30 | +#define WAV_RIFX COMPOSE_ID('R','I','F','X') | ||
31 | +#define WAV_WAVE COMPOSE_ID('W','A','V','E') | ||
32 | +#define WAV_FMT COMPOSE_ID('f','m','t',' ') | ||
33 | +#define WAV_DATA COMPOSE_ID('d','a','t','a') | ||
34 | + | ||
35 | +/* WAVE fmt block constants from Microsoft mmreg.h header */ | ||
36 | +#define WAV_FMT_PCM 0x0001 | ||
37 | +#define WAV_FMT_IEEE_FLOAT 0x0003 | ||
38 | +#define WAV_FMT_DOLBY_AC3_SPDIF 0x0092 | ||
39 | +#define WAV_FMT_EXTENSIBLE 0xfffe | ||
40 | + | ||
41 | +/* Used with WAV_FMT_EXTENSIBLE format */ | ||
42 | +#define WAV_GUID_TAG "\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71" | ||
43 | + | ||
44 | +typedef struct { | ||
45 | + u_int magic; /* 'RIFF' */ | ||
46 | + u_int length; /* filelen */ | ||
47 | + u_int type; /* 'WAVE' */ | ||
48 | +} WaveHeader; | ||
49 | + | ||
50 | +typedef struct { | ||
51 | + u_short format; /* see WAV_FMT_* */ | ||
52 | + u_short channels; | ||
53 | + u_int sample_fq; /* frequence of sample */ | ||
54 | + u_int byte_p_sec; | ||
55 | + u_short byte_p_spl; /* samplesize; 1 or 2 bytes */ | ||
56 | + u_short bit_p_spl; /* 8, 12 or 16 bit */ | ||
57 | +} WaveFmtBody; | ||
58 | + | ||
59 | +typedef struct { | ||
60 | + WaveFmtBody format; | ||
61 | + u_short ext_size; | ||
62 | + u_short bit_p_spl; | ||
63 | + u_int channel_mask; | ||
64 | + u_short guid_format; /* WAV_FMT_* */ | ||
65 | + u_char guid_tag[14]; /* WAV_GUID_TAG */ | ||
66 | +} WaveFmtExtensibleBody; | ||
67 | + | ||
68 | +typedef struct { | ||
69 | + u_int type; /* 'data' */ | ||
70 | + u_int length; /* samplecount */ | ||
71 | +} WaveChunkHeader; | ||
72 | + | ||
73 | + | ||
74 | +#endif /* FORMATS */ | ||
75 | diff --git a/src/utils/cplay.c b/src/utils/cplay.c | ||
76 | index 5b749419e731..8882f4d9746d 100644 | ||
77 | --- a/src/utils/cplay.c | ||
78 | +++ b/src/utils/cplay.c | ||
79 | @@ -1,4 +1,6 @@ | ||
80 | /* | ||
81 | + * Copyright 2020 NXP | ||
82 | + * | ||
83 | * This file is provided under a dual BSD/LGPLv2.1 license. When using or | ||
84 | * redistributing this file, you may do so under either license. | ||
85 | * | ||
86 | @@ -73,6 +75,8 @@ | ||
87 | #include "tinycompress/tinycompress.h" | ||
88 | #include "tinycompress/tinymp3.h" | ||
89 | #include "tinycompress/id3_tag_decode.h" | ||
90 | +#include "tinycompress/wave_formats.h" | ||
91 | +#include <alsa/asoundlib.h> | ||
92 | |||
93 | static int verbose; | ||
94 | static const unsigned int DEFAULT_CODEC_ID = SND_AUDIOCODEC_PCM; | ||
95 | @@ -166,6 +170,77 @@ static int parse_mp3_header(struct mp3_header *header, unsigned int *num_channel | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | +static int parse_wav_header(FILE *file, unsigned int *num_channels, unsigned int *sample_rate, | ||
100 | + unsigned int *format) { | ||
101 | + WaveHeader wave_header; | ||
102 | + WaveChunkHeader chunk_header; | ||
103 | + WaveFmtBody fmt_body; | ||
104 | + int more_chunks = 1; | ||
105 | + | ||
106 | + fread(&wave_header, sizeof(WaveHeader), 1, file); | ||
107 | + if ((wave_header.magic != WAV_RIFF) || | ||
108 | + (wave_header.type != WAV_WAVE)) { | ||
109 | + fprintf(stderr, "Error: it is not a riff/wave file\n"); | ||
110 | + return -1; | ||
111 | + } | ||
112 | + | ||
113 | + do { | ||
114 | + fread(&chunk_header, sizeof(WaveChunkHeader), 1, file); | ||
115 | + switch (chunk_header.type) { | ||
116 | + case WAV_FMT: | ||
117 | + fread(&fmt_body, sizeof(WaveFmtBody), 1, file); | ||
118 | + /* If the format header is larger, skip the rest */ | ||
119 | + if (chunk_header.length > sizeof(WaveFmtBody)) | ||
120 | + fseek(file, chunk_header.length - sizeof(WaveFmtBody), SEEK_CUR); | ||
121 | + | ||
122 | + *num_channels = fmt_body.channels; | ||
123 | + *sample_rate = fmt_body.sample_fq; | ||
124 | + | ||
125 | + switch (fmt_body.bit_p_spl) { | ||
126 | + case 8: | ||
127 | + *format = SND_PCM_FORMAT_U8; | ||
128 | + break; | ||
129 | + case 16: | ||
130 | + *format = SND_PCM_FORMAT_S16_LE; | ||
131 | + break; | ||
132 | + case 24: | ||
133 | + switch (fmt_body.byte_p_spl / fmt_body.channels) { | ||
134 | + case 3: | ||
135 | + *format = SND_PCM_FORMAT_S24_3LE; | ||
136 | + break; | ||
137 | + case 4: | ||
138 | + *format = SND_PCM_FORMAT_S24_LE; | ||
139 | + break; | ||
140 | + default: | ||
141 | + fprintf(stderr, "format error\n"); | ||
142 | + return -1; | ||
143 | + } | ||
144 | + break; | ||
145 | + case 32: | ||
146 | + if (fmt_body.format == WAV_FMT_PCM) { | ||
147 | + *format = SND_PCM_FORMAT_S32_LE; | ||
148 | + } else if (fmt_body.format == WAV_FMT_IEEE_FLOAT) { | ||
149 | + *format = SND_PCM_FORMAT_FLOAT_LE; | ||
150 | + } | ||
151 | + break; | ||
152 | + default: | ||
153 | + fprintf(stderr, "format error\n"); | ||
154 | + return -1; | ||
155 | + } | ||
156 | + break; | ||
157 | + case WAV_DATA: | ||
158 | + /* Stop looking for chunks */ | ||
159 | + more_chunks = 0; | ||
160 | + break; | ||
161 | + default: | ||
162 | + /* Unknown chunk, skip bytes */ | ||
163 | + fseek(file, chunk_header.length, SEEK_CUR); | ||
164 | + } | ||
165 | + } while (more_chunks); | ||
166 | + | ||
167 | + return 0; | ||
168 | +} | ||
169 | + | ||
170 | static int print_time(struct compress *compress) | ||
171 | { | ||
172 | unsigned int avail; | ||
173 | @@ -385,6 +460,35 @@ void get_codec_iec(FILE *file, struct compr_config *config, | ||
174 | codec->format = 0; | ||
175 | } | ||
176 | |||
177 | +void get_codec_pcm(FILE *file, struct compr_config *config, | ||
178 | + struct snd_codec *codec) | ||
179 | +{ | ||
180 | + unsigned int channels, rate, format; | ||
181 | + | ||
182 | + if (parse_wav_header(file, &channels, &rate, &format) == -1) { | ||
183 | + fclose(file); | ||
184 | + exit(EXIT_FAILURE); | ||
185 | + } | ||
186 | + | ||
187 | + if (channels > 2 || (format != SND_PCM_FORMAT_S16_LE && format != SND_PCM_FORMAT_S32_LE) || | ||
188 | + rate > 192000) { | ||
189 | + fprintf(stderr, "unsupported wave file\n"); | ||
190 | + fclose(file); | ||
191 | + exit(EXIT_FAILURE); | ||
192 | + } | ||
193 | + | ||
194 | + codec->id = SND_AUDIOCODEC_PCM; | ||
195 | + codec->ch_in = channels; | ||
196 | + codec->ch_out = channels; | ||
197 | + codec->sample_rate = rate; | ||
198 | + codec->bit_rate = 0; | ||
199 | + codec->rate_control = 0; | ||
200 | + codec->profile = SND_AUDIOPROFILE_PCM; | ||
201 | + codec->level = 0; | ||
202 | + codec->ch_mode = 0; | ||
203 | + codec->format = format; | ||
204 | +} | ||
205 | + | ||
206 | void play_samples(char *name, unsigned int card, unsigned int device, | ||
207 | unsigned long buffer_size, unsigned int frag, | ||
208 | unsigned long codec_id) | ||
209 | @@ -411,6 +515,9 @@ void play_samples(char *name, unsigned int card, unsigned int device, | ||
210 | case SND_AUDIOCODEC_IEC61937: | ||
211 | get_codec_iec(file, &config, &codec); | ||
212 | break; | ||
213 | + case SND_AUDIOCODEC_PCM: | ||
214 | + get_codec_pcm(file, &config, &codec); | ||
215 | + break; | ||
216 | default: | ||
217 | fprintf(stderr, "codec ID %ld is not supported\n", codec_id); | ||
218 | exit(EXIT_FAILURE); | ||
219 | -- | ||
220 | 2.27.0 | ||
221 | |||