gps/GPSResources/tcpmp/common/pcm/pcm_soft.c

656 lines
16 KiB
C
Executable File

/*****************************************************************************
*
* 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: pcm_soft.c 585 2006-01-16 09:48:55Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#include "../dyncode/dyncode.h"
#include "pcm_soft.h"
static INLINE int PCMShift(const audio* Format)
{
int Bit = 0;
if (Format->Bits>8) Bit = 1;
if (Format->Bits>16) Bit = 2;
if (!(Format->Flags & PCM_PLANES) && Format->Channels==2)
++Bit;
return Bit;
}
void PCM_Init()
{
}
void PCM_Done()
{
pcm_soft* p;
while ((p = Context()->PCM)!=NULL)
{
Context()->PCM = p->Next;
CodeDone(&p->Code);
free(p);
}
}
#if (!defined(ARM) && !defined(SH3) && !defined(MIPS)) || !defined(CONFIG_DYNCODE)
void PCM_S16_To_S16_Stereo(pcm_soft* This,const planes DstPtr,const constplanes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
const int32_t* Src = SrcPtr[0];
int32_t* Dst = DstPtr[0];
int32_t* DstEnd = Dst + (DstLength >> 2);
if (State->Step == 256)
memcpy(Dst,Src,DstLength);
else
{
int Pos = State->Pos;
int Step = State->Step;
while (Dst != DstEnd)
{
*(Dst++) = Src[Pos >> 8];
Pos += Step;
}
}
}
void PCM_P32_To_S16_Stereo(pcm_soft* This,const planes DstPtr,const constplanes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
const int32_t* SrcA = SrcPtr[0];
const int32_t* SrcB = SrcPtr[1];
int16_t* Dst = DstPtr[0];
int16_t* DstEnd = Dst + (DstLength >> 1);
int UpLimit = (1 << This->Src.FracBits) - 1;
int DownLimit = -(1 << This->Src.FracBits);
int Shift = This->Src.FracBits - This->Dst.FracBits;
if (State->Step == 256)
{
while (Dst != DstEnd)
{
int Left = *(SrcA++);
int Right = *(SrcB++);
if (Left > UpLimit) Left = UpLimit;
if (Left < DownLimit) Left = DownLimit;
if (Right > UpLimit) Right = UpLimit;
if (Right < DownLimit) Right = DownLimit;
Dst[0] = (int16_t)(Left >> Shift);
Dst[1] = (int16_t)(Right >> Shift);
Dst += 2;
}
}
else
{
int Pos = State->Pos;
int Step = State->Step;
while (Dst != DstEnd)
{
int Left = SrcA[Pos >> 8];
int Right = SrcB[Pos >> 8];
if (Left > UpLimit) Left = UpLimit;
if (Left < DownLimit) Left = DownLimit;
if (Right > UpLimit) Right = UpLimit;
if (Right < DownLimit) Right = DownLimit;
Dst[0] = (int16_t)(Left >> Shift);
Dst[1] = (int16_t)(Right >> Shift);
Dst += 2;
Pos += Step;
}
}
}
void PCMUniversal(pcm_soft* This,const planes DstPtr,const constplanes SrcPtr,int DstLength,pcmstate* State,int Volume)
{
const uint8_t* Src[2];
const uint8_t* DstEnd;
uint8_t* Dst[2];
bool_t SrcSwap = This->SrcSwap;
bool_t DstSwap = This->DstSwap;
int DstType = This->DstType;
int SrcType = This->SrcType;
int DstStep = 1 << This->DstShift;
int Pos = State->Pos;
int Step = State->Step;
float SrcScale = 0;
float DstScale = 0;
int SrcUnsigned = This->SrcUnsigned;
int DstUnsigned = This->DstUnsigned;
int UpLimit = (1 << This->Src.FracBits) - 1;
int DownLimit = -(1 << This->Src.FracBits);
int SrcShift = 31 - This->Src.FracBits;
int DstShift = 31 - This->Dst.FracBits;
bool_t OnlyLeft = (This->Dst.Flags & PCM_ONLY_LEFT) != 0;
bool_t OnlyRight = (This->Dst.Flags & PCM_ONLY_RIGHT) != 0;
bool_t VolumeShift = This->Src.Bits >= 23;
if (!This->UseVolume)
Volume = 256;
if (SrcType >= 12) SrcScale = (float)(1 << This->Src.FracBits);
if (DstType >= 12) DstScale = 1.0f/(1 << This->Dst.FracBits);
Dst[0] = (uint8_t*) DstPtr[0];
Dst[1] = (uint8_t*) DstPtr[1];
Src[0] = (uint8_t*) SrcPtr[0];
Src[1] = (uint8_t*) SrcPtr[1];
DstEnd = Dst[0] + DstLength;
// mono,packed
// mono,planar
// stereo,packed
// stereo,planar
while (Dst[0] != DstEnd)
{
int Left;
int Right;
if (SrcUnsigned)
switch (SrcType)
{
default:
case 0:
case 1:
Left = Right = ((uint8_t*)Src[0])[Pos >> 8] - SrcUnsigned;
break;
case 2:
Left = ((uint8_t*)Src[0])[(Pos >> 8)*2] - SrcUnsigned;
Right = ((uint8_t*)Src[0])[(Pos >> 8)*2+1] - SrcUnsigned;
break;
case 3:
Left = ((uint8_t*)Src[0])[(Pos >> 8)] - SrcUnsigned;
Right = ((uint8_t*)Src[1])[(Pos >> 8)] - SrcUnsigned;
break;
case 4:
case 5:
Left = ((uint16_t*)Src[0])[Pos >> 8];
if (SrcSwap)
Left = SWAP16(Left);
Left -= SrcUnsigned;
Right = Left;
break;
case 6:
Left = ((uint16_t*)Src[0])[(Pos >> 8)*2];
Right = ((uint16_t*)Src[0])[(Pos >> 8)*2+1];
if (SrcSwap)
{
Left = SWAP16(Left);
Right = SWAP16(Right);
}
Left -= SrcUnsigned;
Right -= SrcUnsigned;
break;
case 7:
Left = ((uint16_t*)Src[0])[(Pos >> 8)];
Right = ((uint16_t*)Src[1])[(Pos >> 8)];
if (SrcSwap)
{
Left = SWAP16(Left);
Right = SWAP16(Right);
}
Left -= SrcUnsigned;
Right -= SrcUnsigned;
break;
case 8:
case 9:
Left = ((uint32_t*)Src[0])[Pos >> 8];
if (SrcSwap)
Left = SWAP32(Left);
Left -= SrcUnsigned;
Right = Left;
break;
case 10:
Left = ((uint32_t*)Src[0])[(Pos >> 8)*2];
Right = ((uint32_t*)Src[0])[(Pos >> 8)*2+1];
if (SrcSwap)
{
Left = SWAP32(Left);
Right = SWAP32(Right);
}
Left -= SrcUnsigned;
Right -= SrcUnsigned;
break;
case 11:
Left = ((uint32_t*)Src[0])[(Pos >> 8)];
Right = ((uint32_t*)Src[1])[(Pos >> 8)];
if (SrcSwap)
{
Left = SWAP32(Left);
Right = SWAP32(Right);
}
Left -= SrcUnsigned;
Right -= SrcUnsigned;
break;
}
else
switch (SrcType)
{
default:
case 0:
case 1:
Left = Right = ((int8_t*)Src[0])[Pos >> 8];
break;
case 2:
Left = ((int8_t*)Src[0])[(Pos >> 8)*2];
Right = ((int8_t*)Src[0])[(Pos >> 8)*2+1];
break;
case 3:
Left = ((int8_t*)Src[0])[(Pos >> 8)];
Right = ((int8_t*)Src[1])[(Pos >> 8)];
break;
case 4:
case 5:
Left = ((int16_t*)Src[0])[Pos >> 8];
if (SrcSwap)
Left = (int16_t)SWAP16(Left);
Right = Left;
break;
case 6:
Left = ((int16_t*)Src[0])[(Pos >> 8)*2];
Right = ((int16_t*)Src[0])[(Pos >> 8)*2+1];
if (SrcSwap)
{
Left = (int16_t)SWAP16(Left);
Right = (int16_t)SWAP16(Right);
}
break;
case 7:
Left = ((int16_t*)Src[0])[(Pos >> 8)];
Right = ((int16_t*)Src[1])[(Pos >> 8)];
if (SrcSwap)
{
Left = (int16_t)SWAP16(Left);
Right = (int16_t)SWAP16(Right);
}
break;
case 8:
case 9:
Left = ((int32_t*)Src[0])[Pos >> 8];
if (SrcSwap)
Left = (int32_t)SWAP32(Left);
Right = Left;
break;
case 10:
Left = ((int32_t*)Src[0])[(Pos >> 8)*2];
Right = ((int32_t*)Src[0])[(Pos >> 8)*2+1];
if (SrcSwap)
{
Left = (int32_t)SWAP32(Left);
Right = (int32_t)SWAP32(Right);
}
break;
case 11:
Left = ((int32_t*)Src[0])[(Pos >> 8)];
Right = ((int32_t*)Src[1])[(Pos >> 8)];
if (SrcSwap)
{
Left = (int32_t)SWAP32(Left);
Right = (int32_t)SWAP32(Right);
}
break;
case 12:
case 13:
Left = (int)(((float*)Src[0])[Pos >> 8]*SrcScale);
Right = Left;
break;
case 14:
Left = (int)(((float*)Src[0])[(Pos >> 8)*2]*SrcScale);
Right = (int)(((float*)Src[0])[(Pos >> 8)*2+1]*SrcScale);
break;
case 15:
Left = (int)(((float*)Src[0])[(Pos >> 8)]*SrcScale);
Right = (int)(((float*)Src[1])[(Pos >> 8)]*SrcScale);
break;
}
if (Volume != 256)
{
if (VolumeShift)
{
Left = (Left >> 8) * Volume;
Right = (Right >> 8) * Volume;
}
else
{
Left = (Left * Volume) >> 8;
Right = (Right * Volume) >> 8;
}
}
if (Left > UpLimit) Left = UpLimit;
if (Left < DownLimit) Left = DownLimit;
if (Right > UpLimit) Right = UpLimit;
if (Right < DownLimit) Right = DownLimit;
Left <<= SrcShift;
Right <<= SrcShift;
Left >>= DstShift;
Right >>= DstShift;
if (OnlyLeft)
Right = Left;
if (OnlyRight)
Left = Right;
if ((This->Src.Flags ^ This->Dst.Flags) & PCM_SWAPPEDSTEREO)
SwapInt(&Left,&Right);
switch (DstType)
{
default:
case 0:
case 1:
((int8_t*)Dst[0])[0] = (int8_t)(((Left + Right) >> 1) + DstUnsigned);
break;
case 2:
((int8_t*)Dst[0])[0] = (int8_t)(Left + DstUnsigned);
((int8_t*)Dst[0])[1] = (int8_t)(Right + DstUnsigned);
break;
case 3:
((int8_t*)Dst[0])[0] = (int8_t)(Left + DstUnsigned);
((int8_t*)Dst[1])[0] = (int8_t)(Right + DstUnsigned);
break;
case 4:
case 5:
Left = ((Left + Right) >> 1) + DstUnsigned;
if (DstSwap)
Left = SWAP16(Left);
((int16_t*)Dst[0])[0] = (int16_t)Left;
break;
case 6:
Left += DstUnsigned;
Right += DstUnsigned;
if (DstSwap)
{
Left = SWAP16(Left);
Right = SWAP16(Right);
}
((int16_t*)Dst[0])[0] = (int16_t)Left;
((int16_t*)Dst[0])[1] = (int16_t)Right;
break;
case 7:
Left += DstUnsigned;
Right += DstUnsigned;
if (DstSwap)
{
Left = SWAP16(Left);
Right = SWAP16(Right);
}
((int16_t*)Dst[0])[0] = (int16_t)Left;
((int16_t*)Dst[1])[0] = (int16_t)Right;
break;
case 8:
case 9:
Left = ((Left + Right) >> 1) + DstUnsigned;
if (DstSwap)
Left = SWAP32(Left);
((int32_t*)Dst[0])[0] = Left;
break;
case 10:
Left += DstUnsigned;
Right += DstUnsigned;
if (DstSwap)
{
Left = SWAP32(Left);
Right = SWAP32(Right);
}
((int32_t*)Dst[0])[0] = Left;
((int32_t*)Dst[0])[1] = Right;
break;
case 11:
Left += DstUnsigned;
Right += DstUnsigned;
if (DstSwap)
{
Left = SWAP32(Left);
Right = SWAP32(Right);
}
((int32_t*)Dst[0])[0] = Left;
((int32_t*)Dst[1])[0] = Right;
break;
case 12:
case 13:
Left = (Left + Right) >> 1;
((float*)Dst[0])[0] = (float)Left*DstScale;
break;
case 14:
((float*)Dst[0])[0] = (float)Left*DstScale;
((float*)Dst[0])[1] = (float)Right*DstScale;
break;
case 15:
((float*)Dst[0])[0] = (float)Left*DstScale;
((float*)Dst[1])[0] = (float)Right*DstScale;
break;
}
Pos += Step;
Dst[0] += DstStep;
Dst[1] += DstStep;
}
}
static int UniversalType(const audio* Format)
{
int Type = (Format->Channels - 1)*2;
if (Format->Flags & PCM_PLANES) Type |= 1;
if (Format->Flags & PCM_FLOAT)
Type += 12;
else
{
if (Format->Bits>8) Type += 4;
if (Format->Bits>16) Type += 4;
}
return Type;
}
#endif
pcm_soft* PCMCreate(const audio* DstFormat, const audio* SrcFormat, bool_t Dither, bool_t UseVolume)
{
pcm_soft* p = Context()->PCM;
if (p)
Context()->PCM = p->Next;
else
{
p = (pcm_soft*)malloc(sizeof(pcm_soft));
if (!p)
return NULL;
memset(p,0,sizeof(pcm_soft));
CodeInit(&p->Code);
}
if (!EqAudio(&p->Dst,DstFormat) ||
!EqAudio(&p->Src,SrcFormat) ||
p->UseVolume != UseVolume ||
p->Dither != Dither)
{
p->Entry = NULL;
p->Dst = *DstFormat;
p->Src = *SrcFormat;
p->Dither = Dither;
p->UseVolume = UseVolume;
// only PCM streams are supported
if (p->Dst.Format==AUDIOFMT_PCM && p->Src.Format==AUDIOFMT_PCM)
{
p->SrcSwap = (p->Src.Flags & PCM_SWAPEDBYTES)!=0 && (p->Src.Bits>8);
p->DstSwap = (p->Dst.Flags & PCM_SWAPEDBYTES)!=0 && (p->Dst.Bits>8);
p->SrcShift = PCMShift(&p->Src);
p->DstShift = PCMShift(&p->Dst);
p->SrcUnsigned = (p->Src.Flags & PCM_UNSIGNED) ? (1 << (p->Src.Bits-1)):0;
p->DstUnsigned = (p->Dst.Flags & PCM_UNSIGNED) ? (1 << (p->Dst.Bits-1)):0;
p->UseLeft = (p->Dst.Flags & PCM_ONLY_RIGHT)==0 || (p->Src.Channels <= 1);
p->UseRight = (p->Dst.Flags & PCM_ONLY_LEFT)==0 && (p->Src.Channels > 1);
p->SrcChannels = (p->UseLeft && p->UseRight) ? 2:1;
p->Clip = (p->Src.Bits - p->Src.FracBits) - (p->Dst.Bits - p->Dst.FracBits);
p->Stereo = p->SrcChannels > 1 && p->Dst.Channels > 1;
p->Join = !p->Stereo && (p->SrcChannels > 1);
p->Shift = p->Dst.FracBits - p->Src.FracBits - p->Join;
p->LifeDriveFix = !p->UseVolume && !(p->Src.Flags & PCM_LIFEDRIVE_FIX) && (p->Dst.Flags & PCM_LIFEDRIVE_FIX) && p->Dst.Bits==16;
p->ActualDither = !p->LifeDriveFix && !p->UseVolume && p->Dither && ((p->Clip>0) || (p->Shift<0));
p->Limit2 = p->Src.Bits + p->Join - p->Clip - 1;
if (p->UseVolume && p->Src.Bits < 23)
{
p->Shift -= 8;
p->Limit2 += 8;
}
p->MaxLimit = (1 << p->Limit2) - 1;
p->MinLimit = -(1 << p->Limit2);
p->State.Speed = -1;
p->State.Step = 256;
#if (defined(ARM) || defined(SH3) || defined(MIPS)) && defined(CONFIG_DYNCODE)
CodeStart(&p->Code);
PCMCompile(p);
CodeBuild(&p->Code);
if (p->Code.Size)
p->Entry = (pcmsoftentry)p->Code.Code;
#else
p->SrcType = UniversalType(&p->Src);
p->DstType = UniversalType(&p->Dst);
p->Entry = PCMUniversal;
if (!p->UseVolume && !p->DstUnsigned && p->DstType==6 &&
!((p->Src.Flags ^ p->Dst.Flags) & PCM_SWAPPEDSTEREO) &&
!p->SrcSwap && !p->DstSwap &&
!(p->Dst.Flags & (PCM_ONLY_LEFT|PCM_ONLY_RIGHT)))
{
if (p->Src.FracBits >= p->Dst.FracBits && !p->SrcUnsigned && p->SrcType==11 && !p->SrcSwap && !p->DstSwap)
p->Entry = PCM_P32_To_S16_Stereo;
else
if (p->Src.FracBits == p->Dst.FracBits && !p->SrcUnsigned && p->SrcType==6)
p->Entry = PCM_S16_To_S16_Stereo;
}
#endif
}
}
if (!p->Entry)
{
PCMRelease(p);
p = NULL;
}
PCMReset(p);
return p;
}
void PCMRelease(pcm_soft* p)
{
if (p)
{
p->Next = Context()->PCM;
Context()->PCM = p;
}
}
int PCMDstLength(pcm_soft* p, int SrcLength)
{
return (SrcLength >> p->SrcShift) << p->DstShift;
}
void PCMConvert(pcm_soft* p, const planes Dst, const constplanes Src, int* DstLength, int* SrcLength, int Speed, int Volume)
{
int SrcSamples;
int DstSamples;
int AvailSamples;
if (!p || !p->Entry) return;
SrcSamples = *SrcLength >> p->SrcShift;
DstSamples = *DstLength >> p->DstShift;
if (p->State.Speed != Speed)
{
p->State.Speed = Speed;
p->State.Step = Scale(Speed,p->Src.SampleRate,p->Dst.SampleRate*256);
if (p->State.Step<=0)
p->State.Step = 256;
}
if (p->State.Step != 256)
{
AvailSamples = ((SrcSamples << 8) - p->State.Pos + p->State.Step - 1) / p->State.Step;
if (DstSamples > AvailSamples)
DstSamples = AvailSamples;
AvailSamples = (p->State.Pos + DstSamples * p->State.Step) >> 8;
if (SrcSamples > AvailSamples)
SrcSamples = AvailSamples;
}
else
{
if (DstSamples > SrcSamples)
DstSamples = SrcSamples;
SrcSamples = DstSamples;
}
*SrcLength = SrcSamples << p->SrcShift;
*DstLength = DstSamples << p->DstShift;
if (DstSamples)
p->Entry(p,Dst,Src,*DstLength,&p->State,Volume);
p->State.Pos += (DstSamples * p->State.Step) - (SrcSamples << 8);
}
void PCMReset(pcm_soft* p)
{
if (p)
{
p->State.Pos = 0;
p->State.Dither[0] = 0;
p->State.Dither[1] = 0;
}
}