2 * Copyright (c) 2022 Omar Polo <op@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
20 #include <sys/queue.h>
37 struct mad_stream mad_stream;
38 struct mad_frame mad_frame;
39 struct mad_synth mad_synth;
49 input(void *d, struct mad_stream *stream)
51 struct buffer *buffer = d;
53 if (buffer->length == 0)
56 printf("decode time! start=%p, len=%zu\n", buffer->start, buffer->length);
57 mad_stream_buffer(stream, buffer->start, buffer->length);
59 buffer->sample_rate = 0;
61 return MAD_FLOW_CONTINUE;
64 /* scale a mad sample to 16 bits */
66 scale(mad_fixed_t sample)
69 sample += (1L << (MAD_F_FRACBITS - 16));
72 if (sample >= MAD_F_ONE)
73 sample = MAD_F_ONE - 1;
74 else if (sample < -MAD_F_ONE)
78 return sample >> (MAD_F_FRACBITS + 1 - 16);
82 output(void *data, const struct mad_header *header, struct mad_pcm *pcm)
84 static uint8_t buf[BUFSIZ];
86 struct buffer *buffer = data;
89 const mad_fixed_t *leftch, *rightch;
91 if (player_shouldstop())
94 nsamples = pcm->length;
95 leftch = pcm->samples[0];
96 rightch = pcm->samples[1];
98 if (buffer->sample_rate != pcm->samplerate ||
99 buffer->channels != pcm->channels) {
100 buffer->sample_rate = pcm->samplerate;
101 buffer->channels = pcm->channels;
102 if (player_setup(pcm->samplerate, pcm->channels) == -1)
103 err(1, "player_setrate");
106 for (i = 0, len = 0; i < nsamples; ++i) {
107 if (len+4 >= sizeof(buf)) {
108 sio_write(hdl, buf, len);
109 /* fwrite(buf, 1, len, stdout); */
113 sample = scale(*leftch++);
114 buf[len++] = sample & 0xff;
115 buf[len++] = (sample >> 8) & 0xff;
117 if (pcm->channels == 2) {
118 sample = scale(*rightch++);
119 buf[len++] = sample & 0xff;
120 buf[len++] = (sample >> 8) & 0xff;
125 /* fwrite(buf, 1, len, stdout); */
126 sio_write(hdl, buf, len);
128 return MAD_FLOW_CONTINUE;
132 error(void *d, struct mad_stream *stream, struct mad_frame *frame)
134 struct buffer *buffer = d;
136 warnx("decoding error 0x%04x (%s) at byte offset %zu",
137 stream->error, mad_stream_errorstr(stream),
138 stream->this_frame - (const unsigned char *)buffer->start);
140 return MAD_FLOW_CONTINUE;
144 decode(void *m, size_t len)
146 struct buffer buffer;
147 struct mad_decoder decoder;
150 /* initialize our private message structure; */
154 /* configure input, output and error functions */
155 mad_decoder_init(&decoder, &buffer, input, 0 /* header */,
156 0 /* filter */, output, error, 0 /* message */);
159 result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
161 /* release the decoder */
162 mad_decoder_finish(&decoder);
173 if (fstat(fd, &stat) == -1)
175 warnx("file size %lld", stat.st_size);
177 m = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
181 decode(m, stat.st_size);
182 munmap(m, stat.st_size);