minimad

/**  

002  * libmad - MPEG audio decoder library  

003  * Copyright (C) 2000-2004 Underbit Technologies, Inc.  

004  *  

005  * This program is free software; you can redistribute it and/or modify  

006  * it under the terms of the GNU General Public License as published by  

007  * the Free Software Foundation; either version 2 of the License, or  

008  * (at your option) any later version.  

009  *  

010  * This program is distributed in the hope that it will be useful,  

011  * but WITHOUT ANY WARRANTY; without even the implied warranty of  

012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  

013  * GNU General Public License for more details.  

014  *  

015  * You should have received a copy of the GNU General Public License  

016  * along with this program; if not, write to the Free Software  

017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  

018  *  

019  * $Id: minimad.c,v 1.4 2004/01/23 09:41:32 rob Exp $  

020  */ 

021    

022 # include <stdio.h>  

023 # include <unistd.h>  

024 # include <sys/stat.h>  

025 # include <sys/mman.h>  

026    

027 # include "mad.h"  

028    

029 /**  

030  * This is perhaps the simplest example use of the MAD high-level API.  

031  * Standard input is mapped into memory via mmap(), then the high-level API  

032  * is invoked with three callbacks: input, output, and error. The output  

033  * callback converts MAD's high-resolution PCM samples to 16 bits, then  

034  * writes them to standard output in little-endian, stereo-interleaved  

035  * format.  

036  */ 

037    

038 static int decode(unsigned char const *, unsigned long);  

039    

040 int main(int argc, char *argv[])  

041 {  

042   struct stat stat;  

043   void *fdm;  

044    

045   if (argc != 1)  

046     return 1;  

047    

048   if (fstat(STDIN_FILENO, &stat) == -1 ||  

049       stat.st_size == 0)  

050     return 2;  

051    

052   fdm = mmap(0, stat.st_size, PROT_READ, MAP_SHARED, STDIN_FILENO, 0);  

053   if (fdm == MAP_FAILED)  

054     return 3;  

055    

056   decode(fdm, stat.st_size);  

057    

058   if (munmap(fdm, stat.st_size) == -1)  

059     return 4;  

060    

061   return 0;  

062 }  

063    

064 /**  

065  * This is a private message structure. A generic pointer to this structure  

066  * is passed to each of the callback functions. Put here any data you need  

067  * to access from within the callbacks.  

068  */ 

069    

070 struct buffer {  

071   unsigned char const *start;  

072   unsigned long length;  

073 };  

074    

075 /**  

076  * This is the input callback. The purpose of this callback is to (re)fill  

077  * the stream buffer which is to be decoded. In this example, an entire file  

078  * has been mapped into memory, so we just call mad_stream_buffer() with the  

079  * address and length of the mapping. When this callback is called a second  

080  * time, we are finished decoding.  

081  */ 

082    

083 static 

084 enum mad_flow input(void *data,  

085             struct mad_stream *stream)  

086 {  

087   struct buffer *buffer = data;  

088    

089   if (!buffer->length)  

090     return MAD_FLOW_STOP;  

091    

092   mad_stream_buffer(stream, buffer->start, buffer->length);  

093    

094   buffer->length = 0;  

095    

096   return MAD_FLOW_CONTINUE;  

097 }  

098    

099 /**  

100  * The following utility routine performs simple rounding, clipping, and  

101  * scaling of MAD's high-resolution samples down to 16 bits. It does not  

102  * perform any dithering or noise shaping, which would be recommended to  

103  * obtain any exceptional audio quality. It is therefore not recommended to  

104  * use this routine if high-quality output is desired.  

105  */ 

106    

107 static inline 

108 signed int scale(mad_fixed_t sample)  

109 {  

110   /** round */ 

111   sample += (1L << (MAD_F_FRACBITS - 16));  

112    

113   /** clip */ 

114   if (sample >= MAD_F_ONE)  

115     sample = MAD_F_ONE - 1;  

116   else if (sample < -MAD_F_ONE)  

117     sample = -MAD_F_ONE;  

118    

119   /** quantize */ 

120   return sample >> (MAD_F_FRACBITS + 1 - 16);  

121 }  

122    

123 /**  

124  * This is the output callback function. It is called after each frame of  

125  * MPEG audio data has been completely decoded. The purpose of this callback  

126  * is to output (or play) the decoded PCM audio.  

127  */ 

128    

129 static 

130 enum mad_flow output(void *data,  

131              struct mad_header const *header,  

132              struct mad_pcm *pcm)  

133 {  

134   unsigned int nchannels, nsamples;  

135   mad_fixed_t const *left_ch, *right_ch;  

136    

137   /** pcm->samplerate contains the sampling frequency */ 

138    

139   nchannels = pcm->channels;  

140   nsamples  = pcm->length;  

141   left_ch   = pcm->samples[0];  

142   right_ch  = pcm->samples[1];  

143    

144   while (nsamples--) {  

145     signed int sample;  

146    

147     /** output sample(s) in 16-bit signed little-endian PCM */ 

148    

149     sample = scale(*left_ch++);  

150     putchar((sample >> 0) & 0xff);  

151     putchar((sample >> 8) & 0xff);  

152    

153     if (nchannels == 2) {  

154       sample = scale(*right_ch++);  

155       putchar((sample >> 0) & 0xff);  

156       putchar((sample >> 8) & 0xff);  

157     }  

158   }  

159    

160   return MAD_FLOW_CONTINUE;  

161 }  

162    

163 /**  

164  * This is the error callback function. It is called whenever a decoding  

165  * error occurs. The error is indicated by stream->error; the list of  

166  * possible MAD_ERROR_* errors can be found in the mad.h (or stream.h)  

167  * header file.  

168  */ 

169    

170 static 

171 enum mad_flow error(void *data,  

172             struct mad_stream *stream,  

173             struct mad_frame *frame)  

174 {  

175   struct buffer *buffer = data;  

176    

177   fprintf(stderr, "decoding error 0x%04x (%s) at byte offset %u\n",  

178       stream->error, mad_stream_errorstr(stream),  

179       stream->this_frame - buffer->start);  

180    

181   /** return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */ 

182    

183   return MAD_FLOW_CONTINUE;  

184 }  

185    

186 /**  

187  * This is the function called by main() above to perform all the decoding.  

188  * It instantiates a decoder object and configures it with the input,  

189  * output, and error callback functions above. A single call to  

190  * mad_decoder_run() continues until a callback function returns  

191  * MAD_FLOW_STOP (to stop decoding) or MAD_FLOW_BREAK (to stop decoding and  

192  * signal an error).  

193  */ 

194    

195 static 

196 int decode(unsigned char const *start, unsigned long length)  

197 {  

198   struct buffer buffer;  

199   struct mad_decoder decoder;  

200   int result;  

201    

202   /** initialize our private message structure */ 

203    

204   buffer.start  = start;  

205   buffer.length = length;  

206    

207   /** configure input, output, and error functions */ 

208    

209   mad_decoder_init(&decoder, &buffer,  

210            input, 0 /** header */, 0 /** filter */, output,  

211            error, 0 /** message */);  

212    

213   /** start decoding */ 

214    

215   result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);  

216    

217   /** release the decoder */ 

218    

219   mad_decoder_finish(&decoder);  

220    

221   return result;  

222 } 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值