waveout.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:8k
源码类别:
Windows CE
开发平台:
C/C++
- /*****************************************************************************
- *
- * This program is free software ; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: waveout.c 548 2006-01-08 22:41:57Z picard $
- *
- * The Core Pocket Media Player
- * Copyright (c) 2004-2005 Gabor Kovacs
- *
- ****************************************************************************/
- #include "common.h"
- void VolumeMul(int Vol,void* Dst,int DstLength,const audio* Format)
- {
- uint8_t *u8,*u8e;
- int16_t *s16,*s16e;
- switch (Format->Bits)
- {
- case 8:
- u8=Dst;
- u8e=u8+DstLength;
- for (;u8!=u8e;++u8)
- {
- int i = (((*u8 - 0x80) * Vol) >> 8) + 0x80;
- *u8 = (uint8_t)(i>255?255:(i<0?0:i));
- }
- break;
- case 16:
- s16=Dst;
- s16e=s16+(DstLength>>1);
- for (;s16!=s16e;++s16)
- {
- int i = (*s16 * Vol) >> 8;
- *s16 = (int16_t)(i>32767?32767:(i<-32768?-32768:i));
- }
- break;
- }
- }
- int VolumeRamp(int Ramp,void* Dst,int DstLength,const audio* Format)
- {
- uint8_t *u8,*u8e;
- int16_t *s16,*s16e;
- int Inc = (10*(1<<RAMPSIZE)) / (Format->Channels * Format->SampleRate);
- if (Inc<=0) Inc=1;
- switch (Format->Bits)
- {
- case 8:
- u8=Dst;
- u8e=u8+DstLength;
- for (;u8!=u8e && Ramp<RAMPLIMIT;++u8,Ramp+=Inc)
- *u8 = (uint8_t)((((*u8 - 0x80) * Ramp) >> RAMPSIZE) + 0x80);
- break;
- case 16:
- s16=Dst;
- s16e=s16+(DstLength>>1);
- for (;s16!=s16e && Ramp<RAMPLIMIT;++s16,Ramp+=Inc)
- *s16 = (int16_t)((*s16 * Ramp) >> RAMPSIZE);
- break;
- default:
- Ramp = RAMPLIMIT;
- break;
- }
- return Ramp;
- }
- static void AlignRate(int* Rate,int Target)
- {
- if (*Rate > Target-16 && *Rate < Target+16)
- *Rate = Target;
- }
- static int UpdateInput(waveout_base* p)
- {
- if (p->Done)
- p->Done(p);
- p->Total = 0;
- p->Dropped = 0;
- if (p->Input.Type == PACKET_AUDIO)
- {
- int Result = ERR_NONE;
- int Try;
- if (p->Input.Format.Audio.Format != AUDIOFMT_PCM)
- {
- PacketFormatClear(&p->Input);
- return ERR_INVALID_DATA;
- }
- if (p->Input.Format.Audio.Channels == 0 ||
- p->Input.Format.Audio.SampleRate == 0)
- return ERR_NONE;
- AlignRate(&p->Input.Format.Audio.SampleRate,8000);
- AlignRate(&p->Input.Format.Audio.SampleRate,11025);
- AlignRate(&p->Input.Format.Audio.SampleRate,16000);
- AlignRate(&p->Input.Format.Audio.SampleRate,22050);
- AlignRate(&p->Input.Format.Audio.SampleRate,44100);
- PacketFormatClear(&p->Output);
- p->Output.Type = PACKET_AUDIO;
- p->Output.Format.Audio = p->Input.Format.Audio;
- p->Output.Format.Audio.Flags = 0;
- p->Dither = 0;
- if (p->Stereo==STEREO_SWAPPED)
- p->Output.Format.Audio.Flags |= PCM_SWAPPEDSTEREO;
- else
- if (p->Stereo!=STEREO_NORMAL)
- {
- p->Output.Format.Audio.Channels = 1;
- if (p->Stereo==STEREO_LEFT)
- p->Output.Format.Audio.Flags |= PCM_ONLY_LEFT;
- if (p->Stereo==STEREO_RIGHT)
- p->Output.Format.Audio.Flags |= PCM_ONLY_RIGHT;
- }
- switch (p->Quality)
- {
- case 0: // low quality for very poor devices
- p->Output.Format.Audio.Bits = 8;
- p->Output.Format.Audio.FracBits = 7;
- p->Output.Format.Audio.Channels = 1;
- p->Output.Format.Audio.SampleRate = 22050;
- break;
- case 1: // no dither and only standard samplerate
- if (p->Output.Format.Audio.Bits > 8)
- {
- p->Output.Format.Audio.Bits = 16;
- p->Output.Format.Audio.FracBits = 15;
- }
- else
- {
- p->Output.Format.Audio.Bits = 8;
- p->Output.Format.Audio.FracBits = 7;
- }
- if (p->Output.Format.Audio.SampleRate >= 44100)
- p->Output.Format.Audio.SampleRate = 44100;
- else
- p->Output.Format.Audio.SampleRate = 22050;
- break;
- default:
- case 2: // original samplerate
- if (p->Output.Format.Audio.Bits > 8)
- {
- p->Output.Format.Audio.Bits = 16;
- p->Output.Format.Audio.FracBits = 15;
- }
- else
- {
- p->Output.Format.Audio.Bits = 8;
- p->Output.Format.Audio.FracBits = 7;
- }
- p->Dither = 1;
- break;
- }
- for (Try=0;;++Try)
- {
- if (p->Output.Format.Audio.Bits <= 8)
- p->Output.Format.Audio.Flags |= PCM_UNSIGNED;
- Result = p->Init(p);
- if (Result == ERR_NONE)
- break;
- if (p->Done)
- p->Done(p);
- if (Try==0)
- {
- if (p->Output.Format.Audio.SampleRate > 36000)
- p->Output.Format.Audio.SampleRate = 44100;
- else
- ++Try;
- }
- if (Try==1)
- {
- if (p->Output.Format.Audio.SampleRate != 22050)
- p->Output.Format.Audio.SampleRate = 22050;
- else
- ++Try;
- }
- #ifdef TARGET_SYMBIAN
- if (Try==2)
- {
- if (p->Output.Format.Audio.SampleRate != 16000)
- p->Output.Format.Audio.SampleRate = 16000;
- else
- ++Try;
- }
- if (Try==3)
- {
- if (p->Output.Format.Audio.SampleRate != 11025)
- p->Output.Format.Audio.SampleRate = 11025;
- else
- ++Try;
- }
- if (Try==4)
- {
- if (p->Output.Format.Audio.SampleRate != 8000)
- p->Output.Format.Audio.SampleRate = 8000;
- else
- ++Try;
- }
- if (Try==5)
- break;
- #else
- if (Try==2)
- {
- if (p->Output.Format.Audio.Channels > 1)
- p->Output.Format.Audio.Channels = 1;
- else
- ++Try;
- }
- if (Try==3)
- {
- if (p->Output.Format.Audio.Bits != 8)
- {
- p->Output.Format.Audio.Bits = 8;
- p->Output.Format.Audio.FracBits = 7;
- }
- else
- ++Try;
- }
- if (Try==4)
- break;
- #endif
- }
- if (Try==5)
- {
- PacketFormatClear(&p->Input);
- if (Result == ERR_DEVICE_ERROR)
- ShowError(p->Node.Class,ERR_ID,Result);
- return Result;
- }
- }
- else
- if (p->Input.Type != PACKET_NONE)
- return ERR_INVALID_DATA;
- return ERR_NONE;
- }
- int WaveOutPCM(waveout_base* p)
- {
- PCMRelease(p->PCM);
- p->PCM = PCMCreate(&p->Output.Format.Audio,&p->Input.Format.Audio,p->Dither,0);
- return p->PCM ? ERR_NONE:ERR_OUT_OF_MEMORY;
- }
- int WaveOutBaseGet(waveout_base* p, int No, void* Data, int Size)
- {
- int Result = ERR_INVALID_PARAM;
- switch (No)
- {
- case OUT_INPUT: GETVALUE(p->Pin,pin); break;
- case OUT_INPUT|PIN_FORMAT: GETVALUE(p->Input,packetformat); break;
- case OUT_INPUT|PIN_PROCESS: GETVALUE(p->Input.Format.Audio.Channels?p->Process:DummyProcess,packetprocess); break;
- case OUT_OUTPUT|PIN_FORMAT: GETVALUE(p->Output,packetformat); break;
- case OUT_TOTAL:GETVALUE(p->Total,int); break;
- case OUT_DROPPED:GETVALUE(p->Dropped,int); break;
- case AOUT_STEREO: GETVALUE(p->Stereo,int); break;
- case AOUT_QUALITY: GETVALUE(p->Quality,int); break;
- case AOUT_TIMER: GETVALUE(&p->Timer,node*); break;
- }
- return Result;
- }
- int WaveOutBaseSet(waveout_base* p, int No, const void* Data, int Size)
- {
- int Result = ERR_INVALID_PARAM;
- switch (No)
- {
- case OUT_INPUT|PIN_FORMAT:
- if (PacketFormatSimilarAudio(&p->Input,(const packetformat*)Data))
- {
- PacketFormatCopy(&p->Input,(const packetformat*)Data);
- return WaveOutPCM(p);
- }
- else
- SETPACKETFORMATCMP(p->Input,packetformat,UpdateInput(p));
- break;
- case OUT_INPUT: SETVALUE(p->Pin,pin,ERR_NONE); break;
- case OUT_TOTAL: SETVALUE(p->Total,int,ERR_NONE); break;
- case OUT_DROPPED: SETVALUE(p->Dropped,int,ERR_NONE); break;
- case AOUT_STEREO: SETVALUECMP(p->Stereo,int,UpdateInput(p),EqInt); break;
- case AOUT_QUALITY: SETVALUECMP(p->Quality,int,UpdateInput(p),EqInt); break;
- }
- return Result;
- }