summaryrefslogtreecommitdiffstats
path: root/recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch')
-rwxr-xr-xrecipes-multimedia/tinycompress/tinycompress/0002-cplay-Support-wave-file.patch221
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 @@
1From 4d4bc0a958fe254531920095fbabc241aad88113 Mon Sep 17 00:00:00 2001
2From: Shengjiu Wang <shengjiu.wang@nxp.com>
3Date: Tue, 28 Jul 2020 13:00:36 +0800
4Subject: [PATCH] cplay: Support wave file
5
6The supported format is mono/stereo, S16_LE/S32_LE, 8kHz-192kHz.
7Command is:
8cplay -c x -I PCM test.wav
9
10Upstream-Status: Inappropriate [i.MX specific]
11Signed-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
18diff --git a/include/tinycompress/wave_formats.h b/include/tinycompress/wave_formats.h
19new file mode 100644
20index 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 */
75diff --git a/src/utils/cplay.c b/src/utils/cplay.c
76index 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--
2202.27.0
221