ALvoid aluInitPanning(ALCdevice *Device) { ALfloat SpeakerAngle[MAXCHANNELS]; enum Channel *Speaker2Chan; ALfloat Alpha, Theta; ALint pos; ALuint s; Speaker2Chan = Device->Speaker2Chan; switch(Device->FmtChans) { case DevFmtMono: Device->NumChan = 1; Speaker2Chan[0] = FRONT_CENTER; SpeakerAngle[0] = F_PI/180.0f * 0.0f; break; case DevFmtStereo: Device->NumChan = 2; Speaker2Chan[0] = FRONT_LEFT; Speaker2Chan[1] = FRONT_RIGHT; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * 90.0f; SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtQuad: Device->NumChan = 4; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_RIGHT; Speaker2Chan[3] = BACK_RIGHT; SpeakerAngle[0] = F_PI/180.0f * -135.0f; SpeakerAngle[1] = F_PI/180.0f * -45.0f; SpeakerAngle[2] = F_PI/180.0f * 45.0f; SpeakerAngle[3] = F_PI/180.0f * 135.0f; SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX51: Device->NumChan = 5; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_CENTER; Speaker2Chan[3] = FRONT_RIGHT; Speaker2Chan[4] = BACK_RIGHT; SpeakerAngle[0] = F_PI/180.0f * -110.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 110.0f; SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX51Side: Device->NumChan = 5; Speaker2Chan[0] = SIDE_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_CENTER; Speaker2Chan[3] = FRONT_RIGHT; Speaker2Chan[4] = SIDE_RIGHT; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 90.0f; SetSpeakerArrangement("layout_51SIDECHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX61: Device->NumChan = 6; Speaker2Chan[0] = SIDE_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_CENTER; Speaker2Chan[3] = FRONT_RIGHT; Speaker2Chan[4] = SIDE_RIGHT; Speaker2Chan[5] = BACK_CENTER; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 90.0f; SpeakerAngle[5] = F_PI/180.0f * 180.0f; SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX71: Device->NumChan = 7; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = SIDE_LEFT; Speaker2Chan[2] = FRONT_LEFT; Speaker2Chan[3] = FRONT_CENTER; Speaker2Chan[4] = FRONT_RIGHT; Speaker2Chan[5] = SIDE_RIGHT; Speaker2Chan[6] = BACK_RIGHT; SpeakerAngle[0] = F_PI/180.0f * -150.0f; SpeakerAngle[1] = F_PI/180.0f * -90.0f; SpeakerAngle[2] = F_PI/180.0f * -30.0f; SpeakerAngle[3] = F_PI/180.0f * 0.0f; SpeakerAngle[4] = F_PI/180.0f * 30.0f; SpeakerAngle[5] = F_PI/180.0f * 90.0f; SpeakerAngle[6] = F_PI/180.0f * 150.0f; SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; } for(pos = 0; pos < LUT_NUM; pos++) { ALfloat *PanningLUT = Device->PanningLUT[pos]; /* clear all values */ for(s = 0; s < MAXCHANNELS; s++) PanningLUT[s] = 0.0f; if(Device->NumChan == 1) { PanningLUT[Speaker2Chan[0]] = 1.0f; continue; } /* source angle */ Theta = aluLUTpos2Angle(pos); /* set panning values */ for(s = 0; s < Device->NumChan - 1; s++) { if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1]) { /* source between speaker s and speaker s+1 */ Alpha = (Theta-SpeakerAngle[s]) / (SpeakerAngle[s+1]-SpeakerAngle[s]); PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha); PanningLUT[Speaker2Chan[s+1]] = aluSqrt( Alpha); break; } } if(s == Device->NumChan - 1) { /* source between last and first speaker */ if(Theta < SpeakerAngle[0]) Theta += F_PI*2.0f; Alpha = (Theta-SpeakerAngle[s]) / (F_PI*2.0f + SpeakerAngle[0]-SpeakerAngle[s]); PanningLUT[Speaker2Chan[s]] = aluSqrt(1.0f-Alpha); PanningLUT[Speaker2Chan[0]] = aluSqrt( Alpha); } } }
ALvoid aluInitPanning(ALCdevice *Device) { const char *layoutname = NULL; enum Channel *Speaker2Chan; ALfloat *SpeakerAngle; Speaker2Chan = Device->Speaker2Chan; SpeakerAngle = Device->SpeakerAngle; switch(Device->FmtChans) { case DevFmtMono: Device->NumChan = 1; Speaker2Chan[0] = FrontCenter; SpeakerAngle[0] = F_PI/180.0f * 0.0f; layoutname = NULL; break; case DevFmtStereo: Device->NumChan = 2; Speaker2Chan[0] = FrontLeft; Speaker2Chan[1] = FrontRight; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * 90.0f; layoutname = "layout_stereo"; break; case DevFmtQuad: Device->NumChan = 4; Speaker2Chan[0] = BackLeft; Speaker2Chan[1] = FrontLeft; Speaker2Chan[2] = FrontRight; Speaker2Chan[3] = BackRight; SpeakerAngle[0] = F_PI/180.0f * -135.0f; SpeakerAngle[1] = F_PI/180.0f * -45.0f; SpeakerAngle[2] = F_PI/180.0f * 45.0f; SpeakerAngle[3] = F_PI/180.0f * 135.0f; layoutname = "layout_quad"; break; case DevFmtX51: Device->NumChan = 5; Speaker2Chan[0] = BackLeft; Speaker2Chan[1] = FrontLeft; Speaker2Chan[2] = FrontCenter; Speaker2Chan[3] = FrontRight; Speaker2Chan[4] = BackRight; SpeakerAngle[0] = F_PI/180.0f * -110.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 110.0f; layoutname = "layout_surround51"; break; case DevFmtX51Side: Device->NumChan = 5; Speaker2Chan[0] = SideLeft; Speaker2Chan[1] = FrontLeft; Speaker2Chan[2] = FrontCenter; Speaker2Chan[3] = FrontRight; Speaker2Chan[4] = SideRight; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 90.0f; layoutname = "layout_side51"; break; case DevFmtX61: Device->NumChan = 6; Speaker2Chan[0] = SideLeft; Speaker2Chan[1] = FrontLeft; Speaker2Chan[2] = FrontCenter; Speaker2Chan[3] = FrontRight; Speaker2Chan[4] = SideRight; Speaker2Chan[5] = BackCenter; SpeakerAngle[0] = F_PI/180.0f * -90.0f; SpeakerAngle[1] = F_PI/180.0f * -30.0f; SpeakerAngle[2] = F_PI/180.0f * 0.0f; SpeakerAngle[3] = F_PI/180.0f * 30.0f; SpeakerAngle[4] = F_PI/180.0f * 90.0f; SpeakerAngle[5] = F_PI/180.0f * 180.0f; layoutname = "layout_surround61"; break; case DevFmtX71: Device->NumChan = 7; Speaker2Chan[0] = BackLeft; Speaker2Chan[1] = SideLeft; Speaker2Chan[2] = FrontLeft; Speaker2Chan[3] = FrontCenter; Speaker2Chan[4] = FrontRight; Speaker2Chan[5] = SideRight; Speaker2Chan[6] = BackRight; SpeakerAngle[0] = F_PI/180.0f * -150.0f; SpeakerAngle[1] = F_PI/180.0f * -90.0f; SpeakerAngle[2] = F_PI/180.0f * -30.0f; SpeakerAngle[3] = F_PI/180.0f * 0.0f; SpeakerAngle[4] = F_PI/180.0f * 30.0f; SpeakerAngle[5] = F_PI/180.0f * 90.0f; SpeakerAngle[6] = F_PI/180.0f * 150.0f; layoutname = "layout_surround71"; break; } if(layoutname && Device->Type != Loopback) SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan); }
ALvoid aluInitPanning(ALCdevice *Device) { ALfloat SpeakerAngle[MAXCHANNELS]; ALfloat (*Matrix)[MAXCHANNELS]; Channel *Speaker2Chan; ALfloat Alpha, Theta; ALfloat *PanningLUT; ALint pos, offset; ALuint s, s2; for(s = 0;s < MAXCHANNELS;s++) { for(s2 = 0;s2 < MAXCHANNELS;s2++) Device->ChannelMatrix[s][s2] = ((s==s2) ? 1.0f : 0.0f); } Speaker2Chan = Device->Speaker2Chan; Matrix = Device->ChannelMatrix; switch(Device->FmtChans) { case DevFmtMono: Matrix[FRONT_LEFT][FRONT_CENTER] = aluSqrt(0.5); Matrix[FRONT_RIGHT][FRONT_CENTER] = aluSqrt(0.5); Matrix[SIDE_LEFT][FRONT_CENTER] = aluSqrt(0.5); Matrix[SIDE_RIGHT][FRONT_CENTER] = aluSqrt(0.5); Matrix[BACK_LEFT][FRONT_CENTER] = aluSqrt(0.5); Matrix[BACK_RIGHT][FRONT_CENTER] = aluSqrt(0.5); Matrix[BACK_CENTER][FRONT_CENTER] = 1.0f; Device->NumChan = 1; Speaker2Chan[0] = FRONT_CENTER; SpeakerAngle[0] = 0.0f * M_PI/180.0f; break; case DevFmtStereo: Matrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5); Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5); Matrix[SIDE_LEFT][FRONT_LEFT] = 1.0f; Matrix[SIDE_RIGHT][FRONT_RIGHT] = 1.0f; Matrix[BACK_LEFT][FRONT_LEFT] = 1.0f; Matrix[BACK_RIGHT][FRONT_RIGHT] = 1.0f; Matrix[BACK_CENTER][FRONT_LEFT] = aluSqrt(0.5); Matrix[BACK_CENTER][FRONT_RIGHT] = aluSqrt(0.5); Device->NumChan = 2; Speaker2Chan[0] = FRONT_LEFT; Speaker2Chan[1] = FRONT_RIGHT; SpeakerAngle[0] = -90.0f * M_PI/180.0f; SpeakerAngle[1] = 90.0f * M_PI/180.0f; SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtQuad: Matrix[FRONT_CENTER][FRONT_LEFT] = aluSqrt(0.5); Matrix[FRONT_CENTER][FRONT_RIGHT] = aluSqrt(0.5); Matrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5); Matrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5); Matrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5); Matrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5); Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5); Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5); Device->NumChan = 4; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_RIGHT; Speaker2Chan[3] = BACK_RIGHT; SpeakerAngle[0] = -135.0f * M_PI/180.0f; SpeakerAngle[1] = -45.0f * M_PI/180.0f; SpeakerAngle[2] = 45.0f * M_PI/180.0f; SpeakerAngle[3] = 135.0f * M_PI/180.0f; SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX51: Matrix[SIDE_LEFT][FRONT_LEFT] = aluSqrt(0.5); Matrix[SIDE_LEFT][BACK_LEFT] = aluSqrt(0.5); Matrix[SIDE_RIGHT][FRONT_RIGHT] = aluSqrt(0.5); Matrix[SIDE_RIGHT][BACK_RIGHT] = aluSqrt(0.5); Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5); Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5); Device->NumChan = 5; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_CENTER; Speaker2Chan[3] = FRONT_RIGHT; Speaker2Chan[4] = BACK_RIGHT; SpeakerAngle[0] = -110.0f * M_PI/180.0f; SpeakerAngle[1] = -30.0f * M_PI/180.0f; SpeakerAngle[2] = 0.0f * M_PI/180.0f; SpeakerAngle[3] = 30.0f * M_PI/180.0f; SpeakerAngle[4] = 110.0f * M_PI/180.0f; SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX61: Matrix[BACK_LEFT][BACK_CENTER] = aluSqrt(0.5); Matrix[BACK_LEFT][SIDE_LEFT] = aluSqrt(0.5); Matrix[BACK_RIGHT][BACK_CENTER] = aluSqrt(0.5); Matrix[BACK_RIGHT][SIDE_RIGHT] = aluSqrt(0.5); Device->NumChan = 6; Speaker2Chan[0] = SIDE_LEFT; Speaker2Chan[1] = FRONT_LEFT; Speaker2Chan[2] = FRONT_CENTER; Speaker2Chan[3] = FRONT_RIGHT; Speaker2Chan[4] = SIDE_RIGHT; Speaker2Chan[5] = BACK_CENTER; SpeakerAngle[0] = -90.0f * M_PI/180.0f; SpeakerAngle[1] = -30.0f * M_PI/180.0f; SpeakerAngle[2] = 0.0f * M_PI/180.0f; SpeakerAngle[3] = 30.0f * M_PI/180.0f; SpeakerAngle[4] = 90.0f * M_PI/180.0f; SpeakerAngle[5] = 180.0f * M_PI/180.0f; SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; case DevFmtX71: Matrix[BACK_CENTER][BACK_LEFT] = aluSqrt(0.5); Matrix[BACK_CENTER][BACK_RIGHT] = aluSqrt(0.5); Device->NumChan = 7; Speaker2Chan[0] = BACK_LEFT; Speaker2Chan[1] = SIDE_LEFT; Speaker2Chan[2] = FRONT_LEFT; Speaker2Chan[3] = FRONT_CENTER; Speaker2Chan[4] = FRONT_RIGHT; Speaker2Chan[5] = SIDE_RIGHT; Speaker2Chan[6] = BACK_RIGHT; SpeakerAngle[0] = -150.0f * M_PI/180.0f; SpeakerAngle[1] = -90.0f * M_PI/180.0f; SpeakerAngle[2] = -30.0f * M_PI/180.0f; SpeakerAngle[3] = 0.0f * M_PI/180.0f; SpeakerAngle[4] = 30.0f * M_PI/180.0f; SpeakerAngle[5] = 90.0f * M_PI/180.0f; SpeakerAngle[6] = 150.0f * M_PI/180.0f; SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); break; } if(GetConfigValueBool(NULL, "scalemix", 0)) { ALfloat maxout = 1.0f; for(s = 0;s < MAXCHANNELS;s++) { ALfloat out = 0.0f; for(s2 = 0;s2 < MAXCHANNELS;s2++) out += Device->ChannelMatrix[s2][s]; maxout = __max(maxout, out); } maxout = 1.0f/maxout; for(s = 0;s < MAXCHANNELS;s++) { for(s2 = 0;s2 < MAXCHANNELS;s2++) Device->ChannelMatrix[s2][s] *= maxout; } } PanningLUT = Device->PanningLUT; for(pos = 0; pos < LUT_NUM; pos++) { /* clear all values */ offset = MAXCHANNELS * pos; for(s = 0; s < MAXCHANNELS; s++) PanningLUT[offset+s] = 0.0f; if(Device->NumChan == 1) { PanningLUT[offset + Speaker2Chan[0]] = 1.0f; continue; } /* source angle */ Theta = aluLUTpos2Angle(pos); /* set panning values */ for(s = 0; s < Device->NumChan - 1; s++) { if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1]) { /* source between speaker s and speaker s+1 */ Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / (SpeakerAngle[s+1]-SpeakerAngle[s]); PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); PanningLUT[offset + Speaker2Chan[s+1]] = sin(Alpha); break; } } if(s == Device->NumChan - 1) { /* source between last and first speaker */ if(Theta < SpeakerAngle[0]) Theta += 2.0f * M_PI; Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]); PanningLUT[offset + Speaker2Chan[s]] = cos(Alpha); PanningLUT[offset + Speaker2Chan[0]] = sin(Alpha); } } }