diff --git a/Freeswitch.2008.sln b/Freeswitch.2008.sln
index 9942878717..4b67e0ccd4 100644
--- a/Freeswitch.2008.sln
+++ b/Freeswitch.2008.sln
@@ -467,8 +467,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_dingaling", "src\mod\en
ProjectSection(ProjectDependencies) = postProject
{1906D736-08BD-4EE1-924F-B536249B9A54} = {1906D736-08BD-4EE1-924F-B536249B9A54}
{D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}
- {B4B62169-5AD4-4559-8707-3D933AC5DB39} = {B4B62169-5AD4-4559-8707-3D933AC5DB39}
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
+ {B4B62169-5AD4-4559-8707-3D933AC5DB39} = {B4B62169-5AD4-4559-8707-3D933AC5DB39}
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
{E727E8F6-935D-46FE-8B0E-37834748A0E3} = {E727E8F6-935D-46FE-8B0E-37834748A0E3}
EndProjectSection
@@ -946,6 +946,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_h323", "src\mod\endpoin
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
EndProjectSection
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_iSAC", "src\mod\codecs\mod_isac\mod_iSAC.2008.vcproj", "{7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}"
+ ProjectSection(ProjectDependencies) = postProject
+ {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
+ EndProjectSection
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_skinny", "src\mod\endpoints\mod_skinny\mod_skinny_2008.vcproj", "{CC1DD008-9406-448D-A0AD-33C3186CFADB}"
ProjectSection(ProjectDependencies) = postProject
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
@@ -1137,9 +1142,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openssl", "libs\win32\opens
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_directory", "src\mod\applications\mod_directory\mod_directory.2008.vcproj", "{42E721FD-43D6-4B04-A34B-42567199FFB8}"
+ ProjectSection(ProjectDependencies) = postProject
+ {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ldns", "libs\win32\ldns\ldns-lib\ldns-lib.2008.vcproj", "{23B4D303-79FC-49E0-89E2-2280E7E28940}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_httapi", "src\mod\applications\mod_httapi\mod_httapi.2008.vcproj", "{0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}"
+ ProjectSection(ProjectDependencies) = postProject
+ {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_abstraction", "src\mod\applications\mod_abstraction\mod_abstraction.2008.vcproj", "{BDA173DB-F8EF-4270-9553-B453AF92E43A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
@@ -2405,6 +2423,13 @@ Global
{05C9FB27-480E-4D53-B3B7-7338E2514666}.Debug|x64.ActiveCfg = Debug|x64
{05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|Win32.ActiveCfg = Release|Win32
{05C9FB27-480E-4D53-B3B7-7338E2514666}.Release|x64.ActiveCfg = Release|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|Win32.ActiveCfg = All|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|Win32.Build.0 = All|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x64.ActiveCfg = All|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|x64.ActiveCfg = Debug|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|Win32.ActiveCfg = Release|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|x64.ActiveCfg = Release|x64
{CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|Win32.ActiveCfg = Release|Win32
{CC1DD008-9406-448D-A0AD-33C3186CFADB}.All|x64.ActiveCfg = Release|Win32
{CC1DD008-9406-448D-A0AD-33C3186CFADB}.Debug|Win32.ActiveCfg = Debug|Win32
@@ -2856,6 +2881,28 @@ Global
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|Win32.Build.0 = Release|Win32
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|x64.ActiveCfg = Release|x64
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|x64.Build.0 = Release|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.All|Win32.ActiveCfg = Release|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.All|x64.ActiveCfg = Release|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.All|x64.Build.0 = Release|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Debug|Win32.Build.0 = Debug|Win32
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Debug|x64.ActiveCfg = Debug|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Debug|x64.Build.0 = Debug|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Release|Win32.ActiveCfg = Release|Win32
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Release|Win32.Build.0 = Release|Win32
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Release|x64.ActiveCfg = Release|x64
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169}.Release|x64.Build.0 = Release|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.All|Win32.ActiveCfg = Release|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.All|x64.ActiveCfg = Release|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.All|x64.Build.0 = Release|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Debug|Win32.Build.0 = Debug|Win32
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Debug|x64.ActiveCfg = Debug|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Debug|x64.Build.0 = Debug|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Release|Win32.ActiveCfg = Release|Win32
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Release|Win32.Build.0 = Release|Win32
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Release|x64.ActiveCfg = Release|x64
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2868,6 +2915,7 @@ Global
{8DEB383C-4091-4F42-A56F-C9E46D552D79} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{2C3C2423-234B-4772-8899-D3B137E5CA35} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{0B6C905B-142E-4999-B39D-92FF7951E921} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{D5C87B19-150D-4EF3-A671-96589BD2D14A} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{4D418176-3B33-47E6-A63E-01BA34ADD21C} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{AFA983D6-4569-4F88-BA94-555ED00FD9A8} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
@@ -2903,6 +2951,8 @@ Global
{1E21AFE0-6FDB-41D2-942D-863607C24B91} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{2E250296-0C08-4342-9C8A-BCBDD0E7DF65} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{42E721FD-43D6-4B04-A34B-42567199FFB8} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
+ {0807C5CB-F6FF-451D-89F0-1F7B2E1D9169} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
+ {BDA173DB-F8EF-4270-9553-B453AF92E43A} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{07113B25-D3AF-4E04-BA77-4CD1171F022C} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{A27CCA23-1541-4337-81A4-F0A6413078A0} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln
index cf7053329a..83f9734fa1 100644
--- a/Freeswitch.2010.sln
+++ b/Freeswitch.2010.sln
@@ -453,6 +453,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pthread", "libs\win32\pthre
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_g723_1", "src\mod\codecs\mod_g723_1\mod_g723_1.2010.vcxproj", "{FEA1EEF7-876F-48DE-88BF-C0E3E606D758}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_iSAC", "src\mod\codecs\mod_isac\mod_iSAC.2010.vcxproj", "{7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_native_file", "src\mod\formats\mod_native_file\mod_native_file.2010.vcxproj", "{9254C4B0-6F60-42B6-BB3A-36D63FC001C7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_spidermonkey_core_db", "src\mod\languages\mod_spidermonkey\mod_spidermonkey_core_db.2010.vcxproj", "{ACFFF684-4D19-4D48-AF12-88EA1D778BDF}"
@@ -718,6 +720,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_callcenter", "src\mod\a
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_blacklist", "src\mod\applications\mod_blacklist\mod_blacklist.2010.vcxproj", "{50AAC2CE-BFC9-4912-87CC-C6381850D735}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_httapi", "src\mod\applications\mod_httapi\mod_httapi.2010.vcxproj", "{4748FF56-CA85-4809-97D6-A94C0FAC1D77}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_abstraction", "src\mod\applications\mod_abstraction\mod_abstraction.2010.vcxproj", "{60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
@@ -1428,6 +1434,20 @@ Global
{FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x64.Build.0 = Release Passthrough|x64
{FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x64 Setup.ActiveCfg = Release Passthrough|x64
{FEA1EEF7-876F-48DE-88BF-C0E3E606D758}.Release|x86 Setup.ActiveCfg = Release Passthrough|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|Win32.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x64.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x64.Build.0 = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x64 Setup.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x64 Setup.Build.0 = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.All|x86 Setup.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|x64.ActiveCfg = Debug|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|x64 Setup.ActiveCfg = Debug|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Debug|x86 Setup.ActiveCfg = Debug|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|Win32.ActiveCfg = Release|Win32
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|x64.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|x64 Setup.ActiveCfg = Release|x64
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}.Release|x86 Setup.ActiveCfg = Release|Win32
{9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|Win32.ActiveCfg = Release|x64
{9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64.ActiveCfg = Release|x64
{9254C4B0-6F60-42B6-BB3A-36D63FC001C7}.All|x64.Build.0 = Release|x64
@@ -3680,6 +3700,40 @@ Global
{50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x64.ActiveCfg = Release|x64
{50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x64 Setup.ActiveCfg = Release|x64
{50AAC2CE-BFC9-4912-87CC-C6381850D735}.Release|x86 Setup.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.All|Win32.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.All|x64.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.All|x64.Build.0 = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.All|x64 Setup.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.All|x86 Setup.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|Win32.Build.0 = Debug|Win32
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|x64.ActiveCfg = Debug|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|x64.Build.0 = Debug|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|x64 Setup.ActiveCfg = Debug|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Debug|x86 Setup.ActiveCfg = Debug|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|Win32.ActiveCfg = Release|Win32
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|Win32.Build.0 = Release|Win32
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|x64.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|x64.Build.0 = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|x64 Setup.ActiveCfg = Release|x64
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}.Release|x86 Setup.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.All|Win32.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.All|x64.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.All|x64.Build.0 = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.All|x64 Setup.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.All|x86 Setup.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|Win32.Build.0 = Debug|Win32
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|x64.ActiveCfg = Debug|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|x64.Build.0 = Debug|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|x64 Setup.ActiveCfg = Debug|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Debug|x86 Setup.ActiveCfg = Debug|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|Win32.ActiveCfg = Release|Win32
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|Win32.Build.0 = Release|Win32
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|x64.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|x64.Build.0 = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|x64 Setup.ActiveCfg = Release|x64
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F}.Release|x86 Setup.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3689,6 +3743,7 @@ Global
{5580D60E-0F77-4716-9CD4-B8E5986FA375} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{D3EC0AFF-76FC-4210-A825-9A17410660A3} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{FEA1EEF7-876F-48DE-88BF-C0E3E606D758} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{8DEB383C-4091-4F42-A56F-C9E46D552D79} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{2C3C2423-234B-4772-8899-D3B137E5CA35} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
{0B6C905B-142E-4999-B39D-92FF7951E921} = {F881ADA2-2F1A-4046-9FEB-191D9422D781}
@@ -3730,6 +3785,8 @@ Global
{5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{50AAC2CE-BFC9-4912-87CC-C6381850D735} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
+ {60C542EE-6882-4EA2-8C21-5AB6DB1BA73F} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{07113B25-D3AF-4E04-BA77-4CD1171F022C} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{A27CCA23-1541-4337-81A4-F0A6413078A0} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
diff --git a/build/modules.conf.in b/build/modules.conf.in
index bb8bc7169a..a9993c1e87 100644
--- a/build/modules.conf.in
+++ b/build/modules.conf.in
@@ -15,6 +15,7 @@ applications/mod_hash
#applications/mod_http_cache
#applications/mod_redis
applications/mod_voicemail
+#applications/mod_voicemail_ivr
#applications/mod_directory
#applications/mod_lcr
applications/mod_expr
@@ -40,7 +41,10 @@ applications/mod_valet_parking
#applications/mod_fsk
#applications/mod_ladspa
#applications/mod_mongo
+#applications/mod_abstraction
+#applications/mod_esl
applications/mod_sms
+applications/mod_httapi
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb
@@ -57,6 +61,7 @@ codecs/mod_siren
#codecs/mod_opus
#codecs/mod_sangoma_codec
#codecs/mod_dahdi_codec
+#codecs/mod_isac
#dialplans/mod_dialplan_directory
dialplans/mod_dialplan_xml
dialplans/mod_dialplan_asterisk
diff --git a/conf/autoload_configs/abstraction.conf.xml b/conf/autoload_configs/abstraction.conf.xml
new file mode 100644
index 0000000000..d4b1dfd274
--- /dev/null
+++ b/conf/autoload_configs/abstraction.conf.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/conf/autoload_configs/conference.conf.xml b/conf/autoload_configs/conference.conf.xml
index 0a47f2da30..5a906f91cd 100644
--- a/conf/autoload_configs/conference.conf.xml
+++ b/conf/autoload_configs/conference.conf.xml
@@ -118,6 +118,8 @@
+
+
diff --git a/conf/autoload_configs/directory.conf.xml b/conf/autoload_configs/directory.conf.xml
index 7d99dc1e71..748b2337c4 100644
--- a/conf/autoload_configs/directory.conf.xml
+++ b/conf/autoload_configs/directory.conf.xml
@@ -1,5 +1,7 @@
+
+
diff --git a/conf/autoload_configs/httapi.conf.xml b/conf/autoload_configs/httapi.conf.xml
new file mode 100644
index 0000000000..c2fe584a02
--- /dev/null
+++ b/conf/autoload_configs/httapi.conf.xml
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/autoload_configs/http_cache.conf.xml b/conf/autoload_configs/http_cache.conf.xml
index 4150d6472e..4f05269658 100644
--- a/conf/autoload_configs/http_cache.conf.xml
+++ b/conf/autoload_configs/http_cache.conf.xml
@@ -3,6 +3,8 @@
+
+
diff --git a/conf/autoload_configs/logfile.conf.xml b/conf/autoload_configs/logfile.conf.xml
index 57f276c4ea..65bea552bd 100644
--- a/conf/autoload_configs/logfile.conf.xml
+++ b/conf/autoload_configs/logfile.conf.xml
@@ -10,6 +10,9 @@
+
+
+
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index de4bc40897..50353ac849 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -62,6 +62,7 @@
+
@@ -83,12 +84,14 @@
+
+
diff --git a/conf/autoload_configs/voicemail_ivr.conf.xml b/conf/autoload_configs/voicemail_ivr.conf.xml
new file mode 100644
index 0000000000..b25b4e485d
--- /dev/null
+++ b/conf/autoload_configs/voicemail_ivr.conf.xml
@@ -0,0 +1,208 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/autoload_configs/xml_curl.conf.xml b/conf/autoload_configs/xml_curl.conf.xml
index 21e0af6b68..30951d83c8 100644
--- a/conf/autoload_configs/xml_curl.conf.xml
+++ b/conf/autoload_configs/xml_curl.conf.xml
@@ -1,6 +1,8 @@
+
+
diff --git a/conf/lang/de/demo/demo.xml b/conf/lang/de/demo/demo.xml
index 61582b2052..83ea0d2417 100644
--- a/conf/lang/de/demo/demo.xml
+++ b/conf/lang/de/demo/demo.xml
@@ -52,19 +52,19 @@
-
+
-
+
-
+
-
+
diff --git a/conf/lang/de/vm/tts.xml b/conf/lang/de/vm/tts.xml
index 7a8f18cf50..33367bb88e 100644
--- a/conf/lang/de/vm/tts.xml
+++ b/conf/lang/de/vm/tts.xml
@@ -64,7 +64,7 @@
+ data="Um neue Nachrichten zu hören, drücken Sie $1. Um gespeicherte Nachrichten zu hören, drücken Sie $2, Für erweiterte Optionen, drücken Sie $3. Zum beenden drücken Sie $4."/>
@@ -74,7 +74,7 @@
+ data="Um eine Ansage aufzunehmen, drücken Sie $1. Um eine Ansage auszuwählen, drücken Sie $2. Um ihren Namen aufzunehmen, drücken Sie $3. Um zum Hauptmenü zurückzukehren, drücken Sie $4."/>
@@ -83,7 +83,7 @@
-
+
@@ -92,7 +92,7 @@
+ data="Um die Aufzeichnung anzuhören, drücken Sie $1. Um die Aufzeichnung zu speichern, drücken Sie $2. Für eine erneute Aufnahme drücken Sie $3."/>
@@ -101,7 +101,7 @@
+ data="Drücken Sie $1 um diese Nachricht als wichtig zu markieren. Um fortzufahren drücken Sie $2."/>
@@ -110,7 +110,7 @@
+ data="Drücken Sie $1 um die Nachricht erneut zu hören. Um die Nachricht zu speichern, drücken Sie $2. Zum löschen der Nachricht drücken Sie $3. Für die Weiterleitung als Email, drücken Sie $4."/>
@@ -118,7 +118,7 @@
-
+
@@ -126,7 +126,7 @@
-
+
@@ -134,7 +134,7 @@
-
+
@@ -142,7 +142,7 @@
-
+
@@ -150,7 +150,7 @@
-
+
@@ -158,7 +158,7 @@
-
+
diff --git a/conf/lang/en/en.xml b/conf/lang/en/en.xml
index 2ccd513823..33c55197c2 100644
--- a/conf/lang/en/en.xml
+++ b/conf/lang/en/en.xml
@@ -8,6 +8,7 @@
+
diff --git a/conf/lang/en/ivr/sounds.xml b/conf/lang/en/ivr/sounds.xml
index 1e67062061..d2b3e4686a 100644
--- a/conf/lang/en/ivr/sounds.xml
+++ b/conf/lang/en/ivr/sounds.xml
@@ -1,33 +1,61 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/lang/en/vm/sounds.xml b/conf/lang/en/vm/sounds.xml
index e58d4904bb..976fcde32d 100644
--- a/conf/lang/en/vm/sounds.xml
+++ b/conf/lang/en/vm/sounds.xml
@@ -25,6 +25,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/lang/en/vm/voicemail_ivr.xml b/conf/lang/en/vm/voicemail_ivr.xml
new file mode 100644
index 0000000000..de873078a4
--- /dev/null
+++ b/conf/lang/en/vm/voicemail_ivr.xml
@@ -0,0 +1,397 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/sip_profiles/external.xml b/conf/sip_profiles/external.xml
index 27e76a2edb..a709cbb94c 100644
--- a/conf/sip_profiles/external.xml
+++ b/conf/sip_profiles/external.xml
@@ -69,12 +69,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/sip_profiles/internal.xml b/conf/sip_profiles/internal.xml
index c9855c4bfe..b8390c7934 100644
--- a/conf/sip_profiles/internal.xml
+++ b/conf/sip_profiles/internal.xml
@@ -176,12 +176,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/configure.in b/configure.in
index b75a2de39e..9599c2617f 100644
--- a/configure.in
+++ b/configure.in
@@ -537,6 +537,8 @@ if test "x${ac_cv_func_mlockall}" = "xyes"; then
USE_MLOCKALL=yes
;;
*-freebsd*)
+ APR_ADDTO(SWITCH_AM_CFLAGS, -fPIC)
+ APR_ADDTO(SWITCH_AM_CXXFLAGS, -fPIC)
AC_MSG_RESULT([no, broken for non-root users])
;;
*)
diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml
index 58d5a3604f..d073cf447a 100644
--- a/docs/phrase/phrase_en.xml
+++ b/docs/phrase/phrase_en.xml
@@ -186,7 +186,7 @@
-
+
@@ -220,7 +220,7 @@
-
+
@@ -239,8 +239,8 @@
-
-
+
+
@@ -291,10 +291,11 @@
-
-
-
-
+
+
+
+
+
@@ -312,7 +313,6 @@
-
@@ -397,7 +397,7 @@
-
+
@@ -468,8 +468,8 @@
-
-
+
+
@@ -489,13 +489,27 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -509,6 +523,12 @@
+
+
+
+
+
+
diff --git a/docs/phrase/phrase_fr.xml b/docs/phrase/phrase_fr.xml
index 2d5f488152..991895f865 100644
--- a/docs/phrase/phrase_fr.xml
+++ b/docs/phrase/phrase_fr.xml
@@ -178,7 +178,7 @@
-
+
@@ -210,7 +210,7 @@
-
+
@@ -223,7 +223,7 @@
-
+
@@ -240,7 +240,7 @@
-
+
diff --git a/freeswitch.spec b/freeswitch.spec
index f964cd646c..b99f1c68d5 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -429,17 +429,21 @@ export QA_RPATHS=$[ 0x0001|0x0002 ]
# Application Modules
#
######################################################################################################################
-APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_callcenter applications/mod_cidlookup applications/mod_cluechoo \
- applications/mod_commands applications/mod_conference applications/mod_curl applications/mod_db applications/mod_directory \
- applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum \
- applications/mod_esf applications/mod_expr applications/mod_blacklist"
-APPLICATION_MODULES_FM="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit \
- applications/mod_memcache applications/mod_http_cache"
-APPLICATION_MODULES_NY="applications/mod_nibblebill applications/mod_redis applications/mod_rss applications/mod_snom \
- applications/mod_soundtouch applications/mod_spandsp applications/mod_spy applications/mod_stress \
- applications/mod_valet_parking applications/mod_vmd applications/mod_voicemail applications/mod_sms"
+APPLICATION_MODULES_AC="applications/mod_abstraction applications/mod_avmd applications/mod_blacklist \
+ applications/mod_callcenter applications/mod_cidlookup applications/mod_cluechoo \
+ applications/mod_commands applications/mod_conference applications/mod_curl"
+APPLICATION_MODULES_DE="applications/mod_db applications/mod_directory applications/mod_distributor \
+ applications/mod_dptools applications/mod_easyroute applications/mod_enum applications/mod_esf \
+ applications/mod_expr"
+APPLICATION_MODULES_FR="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr \
+ applications/mod_limit applications/mod_memcache applications/mod_http_cache \
+ applications/mod_nibblebill applications/mod_redis applications/mod_rss"
+APPLICATION_MODULES_SZ="applications/mod_sms applications/mod_snom applications/mod_soundtouch \
+ applications/mod_spandsp applications/mod_spy applications/mod_stress \
+ applications/mod_valet_parking applications/mod_vmd applications/mod_voicemail \
+ applications/mod_voicemail_ivr"
-APPLICATIONS_MODULES="$APPLICATION_MODULES_AE $APPLICATION_MODULES_FM $APPLICATION_MODULES_NY $APPLICATION_MODULES_VZ"
+APPLICATIONS_MODULES="$APPLICATION_MODULES_AC $APPLICATION_MODULES_DE $APPLICATION_MODULES_FR $APPLICATION_MODULES_SZ"
######################################################################################################################
#
# Automatic Speech Recognition and Text To Speech Modules
@@ -451,8 +455,8 @@ ASR_TTS_MODULES="asr_tts/mod_pocketsphinx asr_tts/mod_flite asr_tts/mod_unimrcp"
# Codecs
#
######################################################################################################################
-CODECS_MODULES="codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod_celt codecs/mod_codec2 codecs/mod_ilbc codecs/mod_mp4v \
- codecs/mod_opus codecs/mod_silk codecs/mod_siren codecs/mod_theora "
+CODECS_MODULES="codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod_celt codecs/mod_codec2 codecs/mod_ilbc \
+ codecs/mod_mp4v codecs/mod_opus codecs/mod_silk codecs/mod_siren codecs/mod_theora "
#
%if %{build_sng_tc}
CODECS_MODULES+="codecs/mod_sangoma_codec"
@@ -474,15 +478,17 @@ DIRECTORIES_MODULES=""
# Endpoints
#
######################################################################################################################
-ENDPOINTS_MODULES="endpoints/mod_dingaling endpoints/mod_loopback ../../libs/freetdm/mod_freetdm endpoints/mod_portaudio \
- endpoints/mod_sofia endpoints/mod_skinny endpoints/mod_skypopen endpoints/mod_rtmp"
+ENDPOINTS_MODULES="endpoints/mod_dingaling endpoints/mod_loopback ../../libs/freetdm/mod_freetdm \
+ endpoints/mod_portaudio endpoints/mod_sofia endpoints/mod_skinny endpoints/mod_skypopen \
+ endpoints/mod_rtmp"
######################################################################################################################
#
# Event Handlers
#
######################################################################################################################
-EVENT_HANDLERS_MODULES="event_handlers/mod_cdr_csv event_handlers/mod_cdr_sqlite event_handlers/mod_event_socket event_handlers/mod_event_multicast"
+EVENT_HANDLERS_MODULES="event_handlers/mod_cdr_csv event_handlers/mod_cdr_sqlite event_handlers/mod_event_socket \
+ event_handlers/mod_event_multicast"
######################################################################################################################
#
# File and Audio Format Handlers
@@ -749,6 +755,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/extensions.conf
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/mime.types
+%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/abstraction.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/acl.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/alsa.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/blacklist.conf.xml
@@ -805,6 +812,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/unicall.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/unimrcp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/voicemail.conf.xml
+%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/voicemail_ivr.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/xml_cdr.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/xml_curl.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/xml_rpc.conf.xml
@@ -888,6 +896,7 @@ fi
# Modules in Alphabetical Order, please keep them that way..
#
######################################################################################################################
+%{prefix}/mod/mod_abstraction.so*
%{prefix}/mod/mod_amrwb.so*
%{prefix}/mod/mod_avmd.so*
%{prefix}/mod/mod_blacklist.so*
@@ -960,6 +969,7 @@ fi
%{prefix}/mod/mod_valet_parking.so*
%{prefix}/mod/mod_vmd.so*
%{prefix}/mod/mod_voicemail.so*
+%{prefix}/mod/mod_voicemail_ivr.so*
%{prefix}/mod/mod_xml_cdr.so*
%{prefix}/mod/mod_xml_curl.so*
%{prefix}/mod/mod_xml_rpc.so*
diff --git a/libs/curl/lib/select.c b/libs/curl/lib/select.c
index 0f95921513..1abe49ffb7 100644
--- a/libs/curl/lib/select.c
+++ b/libs/curl/lib/select.c
@@ -124,7 +124,7 @@ int Curl_select(curl_socket_t readfd, curl_socket_t writefd, int timeout_ms)
if (writefd != CURL_SOCKET_BAD) {
if (pfd[num].revents & POLLOUT)
ret |= CSELECT_OUT;
- if (pfd[num].revents & POLLERR)
+ if (pfd[num].revents & (POLLERR|POLLHUP))
ret |= CSELECT_ERR;
}
diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index 108b42cf6e..36651e49d8 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -614,8 +614,7 @@ static void clear_line(void)
static void redisplay(void)
{
-#ifdef WIN32
-#else
+#ifndef WIN32
const LineInfo *lf = el_line(el);
const char *c = lf->buffer;
if (!(write_str(prompt_str))) goto done;
@@ -1124,7 +1123,6 @@ int main(int argc, char *argv[])
char dft_cfile[512] = "fs_cli.conf";
#endif
char *home = getenv("HOME");
- char *term = getenv("TERM");
/* Vars for optargs */
int opt;
static struct option options[] = {
@@ -1159,15 +1157,11 @@ int main(int argc, char *argv[])
int argv_quiet = 0;
int loops = 2, reconnect = 0, timeout = 0;
- if (term && (!strncasecmp("screen", term, 6) ||
- !strncasecmp("vt100", term, 5))) {
- feature_level = 1;
- } else {
- feature_level = 0;
- }
#ifdef WIN32
feature_level = 0;
+#else
+ feature_level = 1;
#endif
strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host));
@@ -1357,7 +1351,12 @@ int main(int argc, char *argv[])
}
global_handle = &handle;
global_profile = profile;
- esl_thread_create_detached(msg_thread_run, &handle);
+
+ if (esl_thread_create_detached(msg_thread_run, &handle) != ESL_SUCCESS) {
+ printf("Error starting thread!\n");
+ esl_disconnect(&handle);
+ return 0;
+ }
#ifdef HAVE_EDITLINE
el = el_init(__FILE__, stdin, stdout, stderr);
diff --git a/libs/esl/managed/ManagedEslTest/Program.cs b/libs/esl/managed/ManagedEslTest/Program.cs
index 82f1b964ae..f19c19ceeb 100644
--- a/libs/esl/managed/ManagedEslTest/Program.cs
+++ b/libs/esl/managed/ManagedEslTest/Program.cs
@@ -166,7 +166,7 @@ namespace ManagedEslTest
ESLconnection eslConnection = new ESLconnection(sckClient.Handle.ToInt32());
ESLevent eslEvent = eslConnection.GetInfo();
- string strUuid = eslEvent.GetHeader("UNIQUE-ID");
+ string strUuid = eslEvent.GetHeader("UNIQUE-ID", 0);
eslConnection.SendRecv("myevents");
eslConnection.SendRecv("divert_events on");
diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c
index 5159166ce9..562ee2d84c 100644
--- a/libs/esl/src/esl.c
+++ b/libs/esl/src/esl.c
@@ -72,6 +72,16 @@
#include
#endif
+#ifndef ESL_MIN
+#define ESL_MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+#ifndef ESL_MAX
+#define ESL_MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+#ifndef ESL_CLAMP
+#define ESL_CLAMP(min,max,val) (ESL_MIN(max,ESL_MAX(val,min)))
+#endif
+
/* Written by Marc Espie, public domain */
#define ESL_CTYPE_NUM_CHARS 256
@@ -1187,7 +1197,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
}
rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf) - 1);
- *((char *)handle->socket_buf + rrval) = '\0';
+ *((char *)handle->socket_buf + ESL_CLAMP(0, sizeof(handle->socket_buf) - 1, rrval)) = '\0';
if (rrval == 0) {
if (++zc >= 100) {
@@ -1224,7 +1234,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
sofar = esl_buffer_read(handle->packet_buf, body, len);
} else {
r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf) - 1);
- *((char *)handle->socket_buf + r) = '\0';
+ *((char *)handle->socket_buf + ESL_CLAMP(0, sizeof(handle->socket_buf) - 1, r)) = '\0';
if (r < 0) {
strerror_r(handle->errnum, handle->err, sizeof(handle->err));
diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c
index ead853ea46..1271e46e4f 100644
--- a/libs/esl/src/esl_event.c
+++ b/libs/esl/src/esl_event.c
@@ -285,7 +285,7 @@ ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
{
esl_event_header_t *hp, *lp = NULL, *tp;
- esl_status_t status = ESL_FALSE;
+ esl_status_t status = (esl_status_t) ESL_FALSE;
int x = 0;
esl_ssize_t hlen = -1;
unsigned long hash = 0;
@@ -875,12 +875,12 @@ ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char
if (!(cj = cJSON_Parse(json))) {
- return ESL_FALSE;
+ return (esl_status_t) ESL_FALSE;
}
if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
cJSON_Delete(cj);
- return ESL_FALSE;
+ return (esl_status_t) ESL_FALSE;
}
for (cjp = cj->child; cjp; cjp = cjp->next) {
diff --git a/libs/esl/src/esl_threadmutex.c b/libs/esl/src/esl_threadmutex.c
index 7a84a12d5e..34fa6bb96a 100644
--- a/libs/esl/src/esl_threadmutex.c
+++ b/libs/esl/src/esl_threadmutex.c
@@ -60,7 +60,7 @@ struct esl_thread {
#endif
};
-size_t thread_default_stacksize = 0;
+size_t thread_default_stacksize = 240 * 1024;
void esl_thread_override_default_stacksize(size_t size)
{
@@ -119,7 +119,9 @@ esl_status_t esl_thread_create_detached_ex(esl_thread_function_t func, void *dat
status = ESL_SUCCESS;
goto done;
+
failpthread:
+
pthread_attr_destroy(&thread->attribute);
#endif
diff --git a/libs/freetdm/conf/freetdm.conf.xml b/libs/freetdm/conf/freetdm.conf.xml
index d8fa55c8cb..6177f7d0f5 100644
--- a/libs/freetdm/conf/freetdm.conf.xml
+++ b/libs/freetdm/conf/freetdm.conf.xml
@@ -281,6 +281,253 @@ with the signaling protocols that you can run on top of your I/O interfaces.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/applications/mod_httapi/mod_httapi.2008.vcproj b/src/mod/applications/mod_httapi/mod_httapi.2008.vcproj
new file mode 100644
index 0000000000..36a83970ba
--- /dev/null
+++ b/src/mod/applications/mod_httapi/mod_httapi.2008.vcproj
@@ -0,0 +1,287 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/applications/mod_httapi/mod_httapi.2010.vcxproj b/src/mod/applications/mod_httapi/mod_httapi.2010.vcxproj
new file mode 100644
index 0000000000..8b3c3b71e0
--- /dev/null
+++ b/src/mod/applications/mod_httapi/mod_httapi.2010.vcxproj
@@ -0,0 +1,131 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ mod_httapi
+ {4748FF56-CA85-4809-97D6-A94C0FAC1D77}
+ mod_httapi
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+ {202d7a4e-760d-4d0e-afa1-d7459ced30ff}
+ false
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mod/applications/mod_httapi/mod_httapi.c b/src/mod/applications/mod_httapi/mod_httapi.c
new file mode 100644
index 0000000000..ab674cce46
--- /dev/null
+++ b/src/mod/applications/mod_httapi/mod_httapi.c
@@ -0,0 +1,2864 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II
+ *
+ * mod_httapi.c -- HT-TAPI Hypertext Telephony API
+ *
+ */
+#include
+#include
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_httapi_shutdown);
+SWITCH_MODULE_DEFINITION(mod_httapi, mod_httapi_load, mod_httapi_shutdown, NULL);
+
+typedef struct profile_perms_s {
+ switch_byte_t set_params;
+ switch_byte_t set_vars;
+ switch_byte_t get_vars;
+ switch_byte_t extended_data;
+ switch_byte_t execute_apps;
+ switch_byte_t expand_vars;
+ struct {
+ switch_byte_t enabled;
+ switch_byte_t set_context;
+ switch_byte_t set_dp;
+ switch_byte_t set_cid_name;
+ switch_byte_t set_cid_number;
+ switch_byte_t full_originate;
+ } dial;
+ struct {
+ switch_byte_t enabled;
+ switch_byte_t set_profile;
+ } conference;
+} profile_perms_t;
+
+struct client_s;
+
+typedef struct action_binding_s {
+ char *realm;
+ char *input;
+ char *action;
+ char *error_file;
+ char *match_digits;
+ char *strip;
+ struct client_s *client;
+ struct action_binding_s *parent;
+} action_binding_t;
+
+typedef struct client_profile_s {
+ char *name;
+ char *method;
+ char *url;
+ char *cred;
+ char *bind_local;
+ int disable100continue;
+ uint32_t enable_cacert_check;
+ char *ssl_cert_file;
+ char *ssl_key_file;
+ char *ssl_key_password;
+ char *ssl_version;
+ char *ssl_cacert_file;
+ uint32_t enable_ssl_verifyhost;
+ char *cookie_file;
+ switch_hash_t *vars_map;
+ int auth_scheme;
+ int timeout;
+ profile_perms_t perms;
+ char *ua;
+
+ struct {
+ char *use_profile;
+ } conference_params;
+
+ struct {
+ char *context;
+ char *dp;
+ switch_event_t *app_list;
+ int default_allow;
+ } dial_params;
+
+ struct {
+ switch_event_t *expand_var_list;
+ switch_event_t *set_var_list;
+ switch_event_t *get_var_list;
+ switch_event_t *api_list;
+ int default_allow;
+ } var_params;
+
+} client_profile_t;
+
+#define HTTAPI_MAX_API_BYTES 1024 * 1024
+#define HTTAPI_MAX_FILE_BYTES 1024 * 1024 * 100
+
+typedef struct client_s {
+ switch_memory_pool_t *pool;
+ int fd;
+ switch_buffer_t *buffer;
+ switch_size_t bytes;
+ switch_size_t max_bytes;
+ switch_event_t *headers;
+ switch_event_t *params;
+ switch_event_t *one_time_params;
+ client_profile_t *profile;
+ switch_core_session_t *session;
+ switch_channel_t *channel;
+ action_binding_t *matching_action_binding;
+ action_binding_t *no_matching_action_binding;
+ struct {
+ char *action;
+ char *name;
+ char *file;
+ } record;
+
+ int err;
+ long code;
+} client_t;
+
+typedef struct hash_node {
+ switch_hash_t *hash;
+ struct hash_node *next;
+} hash_node_t;
+
+static struct {
+ switch_memory_pool_t *pool;
+ hash_node_t *hash_root;
+ hash_node_t *hash_tail;
+ switch_hash_t *profile_hash;
+ switch_hash_t *parse_hash;
+ char cache_path[128];
+ int debug;
+ int not_found_expires;
+ int cache_ttl;
+} globals;
+
+
+/* for apr_pstrcat */
+#define DEFAULT_PREBUFFER_SIZE 1024 * 64
+
+struct http_file_source;
+
+struct http_file_context {
+ int samples;
+ switch_file_handle_t fh;
+ char *cache_file;
+ char *meta_file;
+ char *lock_file;
+ char *metadata;
+ time_t expires;
+ switch_file_t *lock_fd;
+ switch_memory_pool_t *pool;
+ int del_on_close;
+ char *dest_url;
+ char *ua;
+ switch_event_t *url_params;
+
+ struct {
+ char *ext;
+ } read;
+
+ struct {
+ char *file_name;
+ char *profile_name;
+ char *file;
+ char *method;
+ char *name;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ } write;
+};
+
+typedef struct http_file_context http_file_context_t;
+typedef switch_status_t (*tag_parse_t)(const char *tag_name, client_t *client, switch_xml_t tag, const char *body);
+
+static void bind_parser(const char *tag_name, tag_parse_t handler)
+{
+ switch_core_hash_insert(globals.parse_hash, tag_name, (void *)(intptr_t)handler);
+}
+
+
+#define HTTAPI_SYNTAX "[debug_on|debug_off]"
+SWITCH_STANDARD_API(httapi_api_function)
+{
+ if (session) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (zstr(cmd)) {
+ goto usage;
+ }
+
+ if (!strcasecmp(cmd, "debug_on")) {
+ globals.debug = 1;
+ } else if (!strcasecmp(cmd, "debug_off")) {
+ globals.debug = 0;
+ } else {
+ goto usage;
+ }
+
+ stream->write_function(stream, "OK\n");
+ return SWITCH_STATUS_SUCCESS;
+
+ usage:
+ stream->write_function(stream, "USAGE: %s\n", HTTAPI_SYNTAX);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match)
+{
+ action_binding_t *action_binding = (action_binding_t *) match->user_data;
+
+ action_binding->client->matching_action_binding = action_binding;
+ action_binding->match_digits = switch_core_strdup(action_binding->client->pool, match->match_digits);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t *match)
+{
+ action_binding_t *action_binding = (action_binding_t *) match->user_data;
+
+ action_binding->client->no_matching_action_binding = action_binding;
+
+ return SWITCH_STATUS_BREAK;
+}
+
+
+static switch_status_t parse_voicemail(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *check = switch_xml_attr(tag, "check");
+ const char *auth = switch_xml_attr(tag, "auth-only");
+ const char *profile = switch_xml_attr(tag, "profile");
+ const char *domain = switch_xml_attr(tag, "domain");
+ const char *id = switch_xml_attr_soft(tag, "id");
+ char *ddom = NULL;
+ char *str;
+ switch_status_t status;
+
+ if (zstr(profile)) profile = "default";
+
+ if (zstr(domain)) {
+ if ((ddom = switch_core_get_variable_dup("domain"))) {
+ domain = ddom;
+ }
+ }
+
+ if (switch_true(check)) {
+ check = "check";
+ } else {
+ check = "";
+ }
+
+ if (switch_true(auth)) {
+ auth = "auth_only";
+ check = "check";
+ } else {
+ auth = "";
+ }
+
+ str = switch_core_session_sprintf(client->session, "%s %s %s %s %s", check, auth, profile, domain, id);
+
+ while(*str == ' ') str++;
+
+ status = switch_core_session_execute_application(client->session, "voicemail", str);
+
+ switch_safe_free(ddom);
+
+ return status;
+}
+
+static switch_status_t parse_break(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ return SWITCH_STATUS_FALSE;
+}
+
+
+static void console_log(const char *level_str, const char *msg)
+{
+ switch_log_level_t level = SWITCH_LOG_DEBUG;
+ if (level_str) {
+ level = switch_log_str2level(level_str);
+ if (level == SWITCH_LOG_INVALID) {
+ level = SWITCH_LOG_DEBUG;
+ }
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, level, "%s", switch_str_nil(msg));
+}
+
+static void console_clean_log(const char *level_str, const char *msg)
+{
+ switch_log_level_t level = SWITCH_LOG_DEBUG;
+ if (level_str) {
+ level = switch_log_str2level(level_str);
+ if (level == SWITCH_LOG_INVALID) {
+ level = SWITCH_LOG_DEBUG;
+ }
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, level, "%s", switch_str_nil(msg));
+}
+
+static switch_status_t parse_get_var(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *var = switch_xml_attr(tag, "name");
+ const char *perm = switch_xml_attr(tag, "permanent");
+
+ if (zstr(var)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing name attribute!");
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+
+ if (client->profile->perms.get_vars &&
+ (!client->profile->var_params.get_var_list || switch_event_check_permission_list(client->profile->var_params.get_var_list, var))) {
+ const char *vval = switch_channel_get_variable(client->channel, var);
+ if (vval) {
+ switch_event_add_header_string(switch_true(perm) ? client->params : client->one_time_params, SWITCH_STACK_BOTTOM, var, vval);
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "variable %s permission denied!\n", var);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+static switch_status_t parse_continue(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_log(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *level = switch_xml_attr(tag, "level");
+ const char *clean = switch_xml_attr(tag, "clean");
+
+ if (switch_true(clean)) {
+ console_clean_log(level, body);
+ } else {
+ console_log(level, body);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_playback(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *file = switch_xml_attr(tag, "file");
+ const char *name = switch_xml_attr(tag, "name");
+ const char *error_file = switch_xml_attr(tag, "error-file");
+ const char *action = switch_xml_attr(tag, "action");
+ const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout");
+ const char *input_timeout_ = switch_xml_attr(tag, "input-timeout");
+ const char *tts_engine = NULL;
+ const char *tts_voice = NULL;
+ char *loops_ = (char *) switch_xml_attr(tag, "loops");
+ int loops = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_ivr_dmachine_t *dmachine = NULL;
+ switch_input_args_t *args = NULL, myargs = { 0 }, nullargs = { 0 };
+ long digit_timeout = 1500;
+ long input_timeout = 5000;
+ long tmp;
+ switch_xml_t bind = NULL;
+ int submit = 0;
+ int input = 0;
+ int speak = 0, say = 0, pause = 0, play = 0, speech = 0;
+ char *sub_action = NULL;
+ action_binding_t *top_action_binding = NULL;
+ const char *say_lang = NULL;
+ const char *say_type = NULL;
+ const char *say_method = NULL;
+ const char *say_gender = NULL;
+ const char *sp_engine = NULL;
+ const char *sp_grammar = NULL;
+
+ if (!strcasecmp(tag_name, "say")) {
+ say_lang = switch_xml_attr(tag, "language");
+ say_type = switch_xml_attr(tag, "type");
+ say_method = switch_xml_attr(tag, "method");
+ say_gender = switch_xml_attr(tag, "gender");
+
+ if (zstr(say_lang) || zstr(say_type) || zstr(say_method) || zstr(body)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "speak: missing required attributes or text! (language) (type) (method) \n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ say = 1;
+
+ } else if (!strcasecmp(tag_name, "speak")) {
+ tts_engine = switch_xml_attr(tag, "engine");
+ tts_voice = switch_xml_attr(tag, "voice");
+
+ if (zstr(tts_engine)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "speak: missing engine attribute!\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ speak = 1;
+ } else if (!strcasecmp(tag_name, "pause")) {
+ const char *ms_ = switch_xml_attr(tag, "milliseconds");
+ pause = atoi(ms_);
+ if (pause < 0) pause = 1000;
+ } else if (!strcasecmp(tag_name, "playback")) {
+ sp_engine = switch_xml_attr(tag, "asr-engine");
+ sp_grammar = switch_xml_attr(tag, "asr-grammar");
+
+ if (sp_grammar && sp_engine) {
+ speech = 1;
+ } else {
+ play = 1;
+ }
+ }
+
+
+ if (zstr(name)) name = "dialed_digits";
+
+ if (loops_) {
+ loops = atoi(loops_);
+
+ if (loops < 0) {
+ loops = -1;
+ }
+ }
+
+ if (digit_timeout_) {
+ tmp = atol(digit_timeout_);
+
+ if (tmp > 0) {
+ digit_timeout = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid digit timeout [%s]\n", digit_timeout_);
+ }
+ }
+
+ if (input_timeout_) {
+ tmp = atol(input_timeout_);
+
+ if (tmp > 0) {
+ input_timeout = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid input timeout [%s]\n", input_timeout_);
+ }
+ }
+
+ if ((bind = switch_xml_child(tag, "bind"))) {
+ action_binding_t *action_binding;
+ const char *realm = "default";
+
+
+ input++;
+
+ top_action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding));
+ top_action_binding->client = client;
+ top_action_binding->action = (char *) action;
+ top_action_binding->error_file = (char *)error_file;
+
+ switch_ivr_dmachine_create(&dmachine, "HTTAPI", NULL, digit_timeout, 0,
+ NULL, digit_nomatch_action_callback, top_action_binding);
+
+ while(bind) {
+ action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding));
+ action_binding->realm = (char *) realm;
+ action_binding->input = bind->txt;
+ action_binding->client = client;
+ action_binding->action = (char *) switch_xml_attr(bind, "action");
+ action_binding->strip = (char *) switch_xml_attr(bind, "strip");
+ action_binding->error_file = (char *) error_file;
+ action_binding->parent = top_action_binding;
+
+ switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
+ bind = bind->next;
+ }
+
+ switch_ivr_dmachine_set_realm(dmachine, realm);
+ myargs.dmachine = dmachine;
+ args = &myargs;
+ }
+
+ if (zstr(file) && !input) {
+ file = body;
+ }
+
+ if (zstr(file) && !(speak || say || pause)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing file attribute!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ do {
+ if (speak) {
+ status = switch_ivr_speak_text(client->session, tts_engine, tts_voice, (char *)body, args);
+ } else if (say) {
+ status = switch_ivr_say(client->session, body, say_lang, say_type, say_method, say_gender, args);
+ } else if (play) {
+ status = switch_ivr_play_file(client->session, NULL, file, args);
+ } else if (speech) {
+ char *result = NULL;
+
+ status = switch_ivr_play_and_detect_speech(client->session, file, sp_engine, sp_grammar, &result, input_timeout, args);
+
+ if (!zstr(result)) {
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, result);
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "detected_speech");
+ submit = 1;
+ break;
+ }
+
+ input_timeout = 0;
+ } else if (pause) {
+ input_timeout = pause;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!switch_channel_ready(client->channel)) {
+ break;
+ }
+
+ if (!input && !pause) {
+ status = switch_channel_ready(client->channel) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+ submit = 1;
+ break;
+ }
+
+ if (input_timeout && status == SWITCH_STATUS_SUCCESS) {
+ if ((status = switch_ivr_sleep(client->session, input_timeout, SWITCH_TRUE, args)) == SWITCH_STATUS_SUCCESS) {
+ status = SWITCH_STATUS_BREAK;
+ }
+ }
+
+ if (status == SWITCH_STATUS_BREAK) {
+ if (error_file) {
+ switch_ivr_play_file(client->session, NULL, error_file, &nullargs);
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, "invalid");
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "invalid");
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ } else if (status == SWITCH_STATUS_FOUND) {
+ status = SWITCH_STATUS_SUCCESS;
+ submit = 1;
+ break;
+ } else if (status != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ } while (loops-- > 0);
+
+
+ if (submit) {
+ if (client->matching_action_binding) {
+ if (client->matching_action_binding->match_digits) {
+
+ if (client->matching_action_binding->strip) {
+ char *pp, *p;
+
+ for(pp = client->matching_action_binding->strip; pp && *pp; pp++) {
+ if ((p = strchr(client->matching_action_binding->match_digits, *pp))) {
+ *p = '\0';
+ }
+ }
+ }
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, name, client->matching_action_binding->match_digits);
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "input_type", "dtmf");
+ }
+
+ if (client->matching_action_binding->action) {
+ sub_action = client->matching_action_binding->action;
+ } else if (client->matching_action_binding->parent && client->matching_action_binding->parent->action) {
+ sub_action = client->matching_action_binding->parent->action;
+ }
+ }
+
+ if (!sub_action && top_action_binding && top_action_binding->action) {
+ sub_action = top_action_binding->action;
+ }
+
+ if (sub_action && client->matching_action_binding && client->matching_action_binding->match_digits) {
+ if (!strncasecmp(sub_action, "dial:", 5)) {
+ char *context = NULL;
+ char *dp = NULL;
+
+ if (client->profile->perms.dial.set_context) {
+ context = switch_core_session_strdup(client->session, sub_action + 5);
+
+ if ((dp = strchr(context, ':'))) {
+ *dp++ = '\0';
+ if (!client->profile->perms.dial.set_dp) {
+ dp = NULL;
+ }
+ }
+ }
+
+ switch_ivr_session_transfer(client->session, client->matching_action_binding->match_digits, dp, context);
+ status = SWITCH_STATUS_FALSE;
+
+ } else {
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", sub_action);
+ }
+ }
+ }
+
+ if (dmachine) {
+ switch_ivr_dmachine_destroy(&dmachine);
+ }
+
+ return status;
+}
+
+static switch_status_t parse_conference(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ char *str;
+ char *dup, *p;
+ const char *profile_name = switch_xml_attr(tag, "profile");
+
+ if (!client->profile->perms.conference.enabled) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Permission Denied!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ dup = switch_core_session_strdup(client->session, body);
+
+ if ((p = strchr(dup, '@'))) {
+ *p = '\0';
+ }
+
+ if (zstr(profile_name) || !client->profile->perms.conference.set_profile) {
+ profile_name = client->profile->conference_params.use_profile;
+ }
+
+ str = switch_core_session_sprintf(client->session, "%s@%s", dup, profile_name);
+ switch_core_session_execute_application(client->session, "conference", str);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_dial(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *context = NULL;
+ const char *dp = NULL;
+ const char *cid_name = NULL;
+ const char *cid_number = NULL;
+
+ if (!client->profile->perms.dial.enabled) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Permission Denied!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (client->profile->perms.dial.set_context) {
+ context = switch_xml_attr(tag, "context");
+ }
+
+ if (client->profile->perms.dial.set_dp) {
+ dp = switch_xml_attr(tag, "dialplan");
+ }
+
+ if (client->profile->perms.dial.set_cid_name) {
+ cid_name = switch_xml_attr(tag, "caller-id-name");
+ }
+
+ if (client->profile->perms.dial.set_cid_number) {
+ cid_number = switch_xml_attr(tag, "caller-id-number");
+ }
+
+ if (client->profile->perms.dial.full_originate && strchr(body, '/')) {
+ char *str;
+
+ if (!cid_name) {
+ cid_name = switch_channel_get_variable(client->channel, "caller_id_name");
+ }
+ if (!cid_number) {
+ cid_number = switch_channel_get_variable(client->channel, "caller_id_number");
+ }
+
+ str = switch_core_session_sprintf(client->session,
+ "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s", cid_name, cid_number, body);
+
+ switch_core_session_execute_application(client->session, "bridge", str);
+ } else {
+ switch_ivr_session_transfer(client->session, body, dp, context);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_sms(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ switch_event_t *event;
+ const char *from_proto = "httapi";
+ const char *to_proto = "sip";
+ const char *to = switch_xml_attr(tag, "to");
+
+ if (to && switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", from_proto);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", to_proto);
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", switch_channel_get_variable(client->channel, "caller_id_number"));
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain");
+
+ if (body) {
+ switch_event_add_body(event, "%s", body);
+ }
+
+ switch_core_chat_send(to_proto, event);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing 'to' Attribute!\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static int check_app_perm(client_t *client, const char *app_name)
+{
+ if (!client->profile->perms.execute_apps) {
+ return 0;
+ }
+
+ return switch_event_check_permission_list(client->profile->dial_params.app_list, app_name);
+}
+
+static switch_status_t parse_execute(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *app_name = switch_xml_attr(tag, "application");
+ const char *data = switch_xml_attr(tag, "data");
+
+ if (zstr(data)) data = body;
+
+ if (zstr(app_name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid app\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!check_app_perm(client, app_name)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Permission Denied!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!client->profile->perms.expand_vars) {
+ const char *p;
+
+ for(p = data; p && *p; p++) {
+ if (*p == '$') {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Expand Variables: Permission Denied!\n");
+ switch_channel_hangup(client->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+ }
+
+ switch_core_session_execute_application(client->session, app_name, data);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_hangup(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *cause_str = switch_xml_attr(tag, "cause");
+ switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+
+ if (zstr(cause_str)) {
+ cause_str = body;
+ }
+
+ if (!zstr(cause_str)) {
+ cause = switch_channel_str2cause(cause_str);
+ }
+
+ switch_channel_hangup(client->channel, cause);
+
+ return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t parse_record_call(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *limit_ = switch_xml_attr(tag, "limit");
+ const char *name = switch_xml_attr(tag, "name");
+ const char *action = switch_xml_attr(tag, "action");
+ const char *record_file;
+
+ int limit = 0;
+
+ if (client->record.file) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (zstr(name)) name = "recorded_file";
+
+ if (!strncasecmp(name, "http://", 7)) {
+ record_file = name;
+ } else {
+ client->record.action = (char *) action;
+ client->record.name = (char *)name;
+ client->record.file = switch_core_session_sprintf(client->session, "%s%s%s.wav",
+ SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(client->session));
+ record_file = client->record.file;
+ }
+
+ if (limit_) {
+ limit = atoi(limit_);
+ if (limit < 0) limit = 0;
+ }
+
+
+ switch_ivr_record_session(client->session, (char *)record_file, limit, NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_record(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *file = switch_xml_attr(tag, "file");
+ const char *name = switch_xml_attr(tag, "name");
+ const char *error_file = switch_xml_attr(tag, "error-file");
+ const char *beep_file = switch_xml_attr(tag, "beep-file");
+ const char *action = switch_xml_attr(tag, "action");
+ const char *sub_action = NULL;
+ const char *digit_timeout_ = switch_xml_attr(tag, "digit-timeout");
+ char *loops_ = (char *) switch_xml_attr(tag, "loops");
+ int loops = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_ivr_dmachine_t *dmachine = NULL;
+ switch_input_args_t *args = NULL, myargs = { 0 };
+ long digit_timeout = 1500;
+ long tmp;
+ int thresh = 200;
+ int silence_hits = 2;
+ int record_limit = 0;
+ char *tmp_record_path = NULL;
+ const char *v;
+ int rtmp;
+ char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
+ char *fname = NULL;
+ char *p, *ext = "wav";
+ switch_xml_t bind;
+ action_binding_t *top_action_binding = NULL;
+ int http = 0;
+
+ switch_uuid_str(uuid_str, sizeof(uuid_str));
+
+ if (zstr(name)) name = "attached_file";
+
+ if (zstr(file)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ fname = switch_core_strdup(client->pool, file);
+
+ for(p = fname; p && *p; p++) {
+ if (*p == '/' || *p == '\\' || *p == '`') {
+ *p = '_';
+ }
+ }
+
+ if ((p = strrchr(fname, '.'))) {
+ *p++ = '\0';
+ ext = p;
+ }
+
+ for(p = fname; p && *p; p++) {
+ if (*p == '.') {
+ *p = '_';
+ }
+ }
+
+ if (!strncasecmp(fname, "http://", 7)) {
+ tmp_record_path = fname;
+ http = 1;
+ } else {
+ tmp_record_path = switch_core_sprintf(client->pool, "%s%s%s_%s.%s",
+ SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, uuid_str, fname, ext);
+ }
+
+ if ((v = switch_xml_attr(tag, "limit"))) {
+ if ((rtmp = atoi(v)) > -1) {
+ record_limit = rtmp;
+ }
+ }
+
+ if ((v = switch_xml_attr(tag, "silence-hits"))) {
+ if ((rtmp = atoi(v)) > -1) {
+ silence_hits = rtmp;
+ }
+ }
+
+ if ((v = switch_xml_attr(tag, "threshold"))) {
+ if ((rtmp = atoi(v)) > -1) {
+ thresh = rtmp;
+ }
+ }
+
+ if (loops_) {
+ loops = atoi(loops_);
+
+ if (loops < 0) {
+ loops = -1;
+ }
+ }
+
+ if (digit_timeout_) {
+ tmp = atol(digit_timeout_);
+
+ if (tmp > 0) {
+ digit_timeout = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid digit timeout [%s]\n", digit_timeout_);
+ }
+ }
+
+ if ((bind = switch_xml_child(tag, "bind"))) {
+ action_binding_t *action_binding;
+ const char *realm = "default";
+
+ top_action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding));
+ top_action_binding->client = client;
+ top_action_binding->action = (char *) action;
+ top_action_binding->error_file = (char *)error_file;
+
+ switch_ivr_dmachine_create(&dmachine, "HTTAPI", NULL, digit_timeout, 0,
+ NULL, digit_nomatch_action_callback, top_action_binding);
+
+ while(bind) {
+ action_binding = switch_core_session_alloc(client->session, sizeof(*action_binding));
+ action_binding->realm = (char *) realm;
+ action_binding->input = bind->txt;
+ action_binding->client = client;
+ action_binding->action = (char *) switch_xml_attr(bind, "action");
+ action_binding->error_file = (char *) error_file;
+ action_binding->parent = top_action_binding;
+
+ switch_ivr_dmachine_bind(dmachine, action_binding->realm, action_binding->input, 0, digit_action_callback, action_binding);
+ bind = bind->next;
+ }
+
+ switch_ivr_dmachine_set_realm(dmachine, realm);
+ myargs.dmachine = dmachine;
+ args = &myargs;
+ }
+
+ if (beep_file) {
+ status = switch_ivr_play_file(client->session, NULL, beep_file, args);
+ }
+
+ if (!switch_channel_ready(client->channel)) {
+ goto end;
+ }
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ switch_file_handle_t fh = { 0 };
+ fh.thresh = thresh;
+ fh.silence_hits = silence_hits;
+
+ status = switch_ivr_record_file(client->session, &fh, tmp_record_path, args, record_limit);
+ }
+
+ if (client->matching_action_binding) {
+ if (client->matching_action_binding->action) {
+ sub_action = client->matching_action_binding->action;
+ } else if (client->matching_action_binding->parent && client->matching_action_binding->parent->action) {
+ sub_action = client->matching_action_binding->parent->action;
+ }
+ }
+
+ if (!sub_action && top_action_binding && top_action_binding->action) {
+ sub_action = top_action_binding->action;
+ }
+
+ if (sub_action) {
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", sub_action);
+ }
+
+ if (!http && !zstr(tmp_record_path) && switch_file_exists(tmp_record_path, client->pool) == SWITCH_STATUS_SUCCESS) {
+ char *key = switch_core_sprintf(client->pool, "attach_file:%s:%s.%s", name, fname, ext);
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, key, tmp_record_path);
+ }
+
+ end:
+
+ if (dmachine) {
+ switch_ivr_dmachine_destroy(&dmachine);
+ }
+
+ return status;
+}
+
+static switch_status_t parse_common(const char *tag_name, client_t *client, switch_xml_t tag, const char *body)
+{
+ const char *action = switch_xml_attr(tag, "action");
+ const char *tmp_action = switch_xml_attr(tag, "temp-action");
+
+ if (action) {
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", action);
+ }
+
+ if (tmp_action) {
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", tmp_action);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t parse_xml(client_t *client)
+{
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ const void *bdata;
+ switch_size_t len;
+ int runs = 0;
+
+ if ((len = switch_buffer_peek_zerocopy(client->buffer, &bdata)) && switch_buffer_len(client->buffer) > len) {
+ switch_xml_t xml, tag, category;
+
+ if (globals.debug) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Debugging Return Data:\n%s\n", (char *)bdata);
+ }
+
+ if ((xml = switch_xml_parse_str((char *)bdata, len))) {
+
+ if (client->profile->perms.set_params) {
+ if ((category = switch_xml_child(xml, "params"))) {
+ tag = category->child;
+
+ while(tag) {
+ if (!zstr(tag->name)) {
+ char *val = tag->txt;
+ if (zstr(val)) {
+ val = NULL;
+ }
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, tag->name, val);
+ }
+ tag = tag->ordered;
+ }
+ }
+ }
+
+ if (client->profile->perms.set_vars) {
+ if ((category = switch_xml_child(xml, "variables"))) {
+ tag = category->child;
+
+ while(tag) {
+ if (!zstr(tag->name)) {
+ char *val = tag->txt;
+ if (zstr(val)) {
+ val = NULL;
+ }
+
+ if (client->profile->perms.set_vars &&
+ (!client->profile->var_params.set_var_list ||
+ switch_event_check_permission_list(client->profile->var_params.set_var_list, tag->name))) {
+ switch_channel_set_variable(client->channel, tag->name, val);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "variable %s permission denied!\n", tag->name);
+ }
+ }
+ tag = tag->ordered;
+ }
+ }
+ }
+
+ if ((category = switch_xml_child(xml, "work"))) {
+
+ tag = category->child;
+ status = SWITCH_STATUS_SUCCESS;
+
+ while(status == SWITCH_STATUS_SUCCESS && tag) {
+ if (!zstr(tag->name)) {
+ tag_parse_t handler;
+
+ if ((handler = (tag_parse_t)(intptr_t) switch_core_hash_find(globals.parse_hash, tag->name))) {
+ char *expanded = tag->txt;
+ switch_event_t *templ_data;
+
+ if (tag->txt && client->profile->perms.expand_vars) {
+ switch_channel_get_variables(client->channel, &templ_data);
+ switch_event_merge(templ_data, client->params);
+ expanded = switch_event_expand_headers_check(templ_data, tag->txt,
+ client->profile->var_params.expand_var_list, client->profile->var_params.api_list);
+ switch_event_destroy(&templ_data);
+ }
+
+ runs++;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Process Tag: [%s]\n", tag->name);
+
+ parse_common(tag->name, client, tag, expanded);
+ status = handler(tag->name, client, tag, expanded);
+
+ if (expanded && expanded != tag->txt) {
+ free(expanded);
+ }
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported Tag: [%s]\n", tag->name);
+ status = SWITCH_STATUS_FALSE;
+ }
+
+ }
+ tag = tag->ordered;
+ }
+ }
+
+ if (!runs) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No instructions found in result!\n");
+ status = SWITCH_STATUS_FALSE;
+ }
+
+
+ switch_xml_free(xml);
+ }
+ }
+
+ return status;
+}
+
+
+static size_t get_header_callback(void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ size_t realsize = (size * nmemb);
+ char *val, *header = NULL;
+ client_t *client = userdata;
+
+ /* validate length... Apache and IIS won't send a header larger than 16 KB */
+ if (realsize == 0 || realsize > 1024 * 16) {
+ return realsize;
+ }
+
+ /* get the header, adding NULL terminator if there isn't one */
+ switch_zmalloc(header, realsize + 1);
+ strncpy(header, (char *)ptr, realsize);
+
+ if ((val = strchr(header, ':'))) {
+ char *cr;
+ *val++ = '\0';
+ while(*val == ' ') val++;
+
+ if ((cr = strchr(val, '\r')) || (cr = strchr(val, '\r'))) {
+ *cr = '\0';
+ }
+
+ switch_event_add_header_string(client->headers, SWITCH_STACK_BOTTOM, header, val);
+ }
+
+ switch_safe_free(header);
+ return realsize;
+}
+
+
+static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+ register unsigned int realsize = (unsigned int) (size * nmemb);
+ client_t *client = data;
+
+ client->bytes += realsize;
+
+ if (client->bytes > client->max_bytes) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) client->bytes);
+ client->err = 1;
+ return 0;
+ }
+
+ switch_buffer_write(client->buffer, ptr, realsize);
+
+ return realsize;
+}
+
+static void client_destroy(client_t **client)
+{
+ if (client && *client) {
+ switch_memory_pool_t *pool;
+
+ switch_event_destroy(&(*client)->headers);
+ switch_event_destroy(&(*client)->params);
+ switch_event_destroy(&(*client)->one_time_params);
+ switch_buffer_destroy(&(*client)->buffer);
+
+ pool = (*client)->pool;
+ switch_core_destroy_memory_pool(&pool);
+ }
+}
+
+static void client_reset(client_t *client)
+{
+ if (client->headers) {
+ switch_event_destroy(&client->headers);
+ }
+
+ switch_event_destroy(&client->one_time_params);
+ switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE);
+ client->one_time_params->flags |= EF_UNIQ_HEADERS;
+
+ switch_event_create(&client->headers, SWITCH_EVENT_CLONE);
+
+
+ switch_buffer_zero(client->buffer);
+
+ client->code = 0;
+ client->err = 0;
+ client->matching_action_binding = NULL;
+ client->no_matching_action_binding = NULL;
+}
+
+static client_t *client_create(switch_core_session_t *session, const char *profile_name, switch_event_t **params)
+{
+ client_t *client;
+ switch_memory_pool_t *pool;
+ client_profile_t *profile;
+
+ if (zstr(profile_name)) {
+ profile_name = "default";
+ }
+
+ profile = (client_profile_t *) switch_core_hash_find(globals.profile_hash, profile_name);
+
+ if (!profile) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile [%s]\n", profile_name);
+ return NULL;
+ }
+
+ switch_core_new_memory_pool(&pool);
+ client = switch_core_alloc(pool, sizeof(*client));
+ client->pool = pool;
+
+ switch_event_create(&client->headers, SWITCH_EVENT_CLONE);
+
+ if (session) {
+ client->session = session;
+ client->channel = switch_core_session_get_channel(session);
+ }
+
+
+ client->profile = profile;
+
+ client->max_bytes = HTTAPI_MAX_API_BYTES;
+
+ switch_buffer_create_dynamic(&client->buffer, 1024, 1024, 0);
+
+ if (params && *params) {
+ client->params = *params;
+ *params = NULL;
+ } else {
+ switch_event_create(&client->params, SWITCH_EVENT_CLONE);
+ client->params->flags |= EF_UNIQ_HEADERS;
+ }
+
+ switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE);
+ client->one_time_params->flags |= EF_UNIQ_HEADERS;
+
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "hostname", switch_core_get_switchname());
+
+ return client;
+}
+
+
+static void cleanup_attachments(client_t *client)
+{
+ switch_event_header_t *hp;
+
+ for (hp = client->params->headers; hp; hp = hp->next) {
+ if (!strncasecmp(hp->name, "attach_file:", 12)) {
+ if (switch_file_exists(hp->value, client->pool)) {
+ printf("DELETE %s\n", hp->value);
+ unlink(hp->value);
+ }
+ }
+ }
+}
+
+size_t put_file_read( void *ptr, size_t size, size_t nmemb, void *userdata)
+{
+ return fread(ptr, size, nmemb, (FILE *) userdata);
+}
+
+static switch_status_t httapi_sync(client_t *client)
+
+{
+ switch_CURL *curl_handle = NULL;
+ char *data = NULL;
+ switch_curl_slist_t *headers = NULL;
+ char *url = NULL;
+ char *dynamic_url = NULL, *use_url = NULL;
+ const char *session_id = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ int get_style_method = 0;
+ char *method = NULL;
+ struct curl_httppost *formpost=NULL;
+ switch_event_t *save_params = NULL;
+ const char *put_file;
+ FILE *fd = NULL;
+ char *creds, *dup_creds = NULL, *ua = NULL;
+
+
+ if (client->one_time_params && client->one_time_params->headers) {
+ save_params = client->params;
+ switch_event_dup(&client->params, save_params);
+ switch_event_merge(client->params, client->one_time_params);
+ switch_event_destroy(&client->one_time_params);
+ switch_event_create(&client->one_time_params, SWITCH_EVENT_CLONE);
+ client->one_time_params->flags |= EF_UNIQ_HEADERS;
+ }
+
+
+ ua = switch_event_get_header(client->params, "user_agent");
+
+ if (zstr(ua)) {
+ ua = client->profile->ua;
+ }
+
+ if (!(session_id = switch_event_get_header(client->params, "HTTAPI_SESSION_ID"))) {
+ if (client->channel && !(session_id = switch_channel_get_variable(client->channel, "HTTAPI_SESSION_ID"))) {
+ session_id = switch_core_session_get_uuid(client->session);
+ }
+ }
+
+ if (client->code || client->err) {
+ client_reset(client);
+ }
+
+
+ if (!(method = switch_event_get_header(client->params, "method"))) {
+ method = client->profile->method;
+ }
+
+ if (!(url = switch_event_get_header(client->params, "url"))) {
+ url = client->profile->url;
+ switch_event_add_header_string(client->params, SWITCH_STACK_BOTTOM, "url", url);
+ }
+
+ get_style_method = method ? strcasecmp(method, "post") : 1;
+
+ switch_event_add_header_string(client->params, SWITCH_STACK_TOP, "session_id", session_id);
+
+ dynamic_url = switch_event_expand_headers(client->params, url);
+
+ if ((put_file = switch_event_get_header(client->params, "put_file"))) {
+ if (!(fd = fopen(put_file, "rb"))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Can't open [%s]\n", put_file);
+ put_file = NULL;
+ }
+ }
+
+ if (!put_file) {
+ switch_curl_process_form_post_params(client->params, curl_handle, &formpost);
+ get_style_method = 1;
+ }
+
+ if (formpost) {
+ get_style_method = 1;
+ } else {
+ data = switch_event_build_param_string(client->params, NULL, client->profile->vars_map);
+ switch_assert(data);
+
+ if (get_style_method) {
+ char *tmp = switch_mprintf("%s%c%s", dynamic_url, strchr(dynamic_url, '?') != NULL ? '&' : '?', data);
+
+ if (dynamic_url != url) {
+ free(dynamic_url);
+ }
+
+ dynamic_url = tmp;
+ }
+ }
+
+
+ if ((use_url = strchr(dynamic_url, '@'))) {
+ char *r, *q, *p = strstr(dynamic_url, "://");
+ use_url++;
+
+ dup_creds = strdup(p+3);
+
+ if ((q = strchr(dup_creds, '@'))) *q = '\0';
+
+ q = strdup(url);
+ r = strchr(q, '@');
+ r++;
+
+ if ((p = strstr(q, "://"))) {
+ *(p+3) = '\0';
+ }
+
+ p = switch_mprintf("%s%s", q, r);
+ free(dynamic_url);
+ dynamic_url = p;
+ free(q);
+ }
+
+
+ if ((use_url = strchr(dynamic_url, '@'))) {
+ char *q, *p = strstr(dynamic_url, "://");
+ use_url++;
+
+ dup_creds = strdup(p+3);
+ *p = '\0';
+
+ if ((q = strchr(dup_creds, '@'))) *q = '\0';
+
+ creds = dup_creds;
+
+ p = switch_mprintf("%s%s", p, use_url);
+ free(dynamic_url);
+ dynamic_url = p;
+ } else {
+ creds = client->profile->cred;
+ }
+
+ curl_handle = switch_curl_easy_init();
+
+ if (session_id) {
+ char *hval = switch_mprintf("HTTAPI_SESSION_ID=%s", session_id);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIE, hval);
+ free(hval);
+ }
+
+ if (!strncasecmp(dynamic_url, "https", 5)) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+
+
+ if (!zstr(creds)) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, client->profile->auth_scheme);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, creds);
+ }
+
+ if (client->profile->disable100continue) {
+ headers = switch_curl_slist_append(headers, "Expect:");
+ }
+
+ if (client->profile->enable_cacert_check) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
+ }
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
+
+ if (method != NULL && strcasecmp(method, "get") && strcasecmp(method, "post")) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, method);
+ }
+
+ if (put_file) {
+ curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(curl_handle, CURLOPT_READDATA, fd);
+ curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, put_file_read);
+
+ } else if (formpost) {
+ curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, formpost);
+ } else {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_POST, !get_style_method);
+ }
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
+
+ if (!get_style_method && !formpost) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, data);
+ }
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_URL, dynamic_url);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) client);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) client);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua);
+
+ if (client->profile->timeout) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, client->profile->timeout);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
+ }
+
+ if (client->profile->ssl_cert_file) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, client->profile->ssl_cert_file);
+ }
+
+ if (client->profile->ssl_key_file) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, client->profile->ssl_key_file);
+ }
+
+ if (client->profile->ssl_key_password) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, client->profile->ssl_key_password);
+ }
+
+ if (client->profile->ssl_version) {
+ if (!strcasecmp(client->profile->ssl_version, "SSLv3")) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
+ } else if (!strcasecmp(client->profile->ssl_version, "TLSv1")) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
+ }
+ }
+
+ if (client->profile->ssl_cacert_file) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, client->profile->ssl_cacert_file);
+ }
+
+ if (client->profile->enable_ssl_verifyhost) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
+ }
+
+ if (client->profile->cookie_file) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, client->profile->cookie_file);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, client->profile->cookie_file);
+ }
+
+ if (client->profile->bind_local) {
+ curl_easy_setopt(curl_handle, CURLOPT_INTERFACE, client->profile->bind_local);
+ }
+
+
+ switch_curl_easy_perform(curl_handle);
+ switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &client->code);
+ switch_curl_easy_cleanup(curl_handle);
+ switch_curl_slist_free_all(headers);
+
+ if (formpost) {
+ curl_formfree(formpost);
+ }
+
+ if (client->err) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error encountered! [%s]\ndata: [%s]\n", client->profile->url, data);
+ status = SWITCH_STATUS_FALSE;
+ } else {
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ switch_safe_free(data);
+ switch_safe_free(dup_creds);
+
+ if (dynamic_url != url) {
+ switch_safe_free(dynamic_url);
+ }
+
+ cleanup_attachments(client);
+
+ if (save_params) {
+ switch_event_destroy(&client->params);
+ client->params = save_params;
+ save_params = NULL;
+ }
+
+ if (fd) {
+ fclose(fd);
+ }
+
+ return status;
+}
+
+#define ENABLE_PARAM_VALUE "enabled"
+static switch_status_t do_config(void)
+{
+ char *cf = "httapi.conf";
+ switch_xml_t cfg, xml, profiles_tag, profile_tag, param, settings, tag;
+ client_profile_t *profile = NULL;
+ int x = 0;
+ int need_vars_map = 0;
+ switch_hash_t *vars_map = NULL;
+
+ if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
+ return SWITCH_STATUS_TERM;
+ }
+
+ if ((settings = switch_xml_child(cfg, "settings"))) {
+ for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "debug")) {
+ globals.debug = switch_true(val);
+ } else if (!strcasecmp(var, "file-cache-ttl")) {
+ int tmp = atoi(val);
+
+ if (tmp > -1) {
+ globals.cache_ttl = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid value [%s]for file-cache-ttl\n", val);
+ }
+
+ } else if (!strcasecmp(var, "file-not-found-expires")) {
+ globals.not_found_expires = atoi(val);
+
+ if (globals.not_found_expires < 0) {
+ globals.not_found_expires = -1;
+ }
+ }
+ }
+ }
+
+ if (!(profiles_tag = switch_xml_child(cfg, "profiles"))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing tag!\n");
+ goto done;
+ }
+
+ for (profile_tag = switch_xml_child(profiles_tag, "profile"); profile_tag; profile_tag = profile_tag->next) {
+ char *bname = (char *) switch_xml_attr_soft(profile_tag, "name");
+ char *url = NULL;
+ char *bind_local = NULL;
+ char *bind_cred = NULL;
+ char *method = NULL;
+ int disable100continue = 1;
+ int timeout = 0;
+ uint32_t enable_cacert_check = 0;
+ char *ssl_cert_file = NULL;
+ char *ssl_key_file = NULL;
+ char *ssl_key_password = NULL;
+ char *ssl_version = NULL;
+ char *ssl_cacert_file = NULL;
+ uint32_t enable_ssl_verifyhost = 0;
+ char *cookie_file = NULL;
+ char *ua = "mod_httapi/1.0";
+ hash_node_t *hash_node;
+ int auth_scheme = CURLAUTH_BASIC;
+ need_vars_map = 0;
+ vars_map = NULL;
+
+ if (zstr(bname)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "profile tag missing name field!\n");
+ continue;
+ }
+
+ if (switch_core_hash_find(globals.profile_hash, bname)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile %s already exists\n", (char *)bname);
+ continue;
+ }
+
+ if ((tag = switch_xml_child(profile_tag, "params"))) {
+ for (param = switch_xml_child(tag, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "gateway-url")) {
+ if (val) {
+ url = val;
+ }
+ } else if (!strcasecmp(var, "user-agent")) {
+ ua = val;
+ } else if (!strcasecmp(var, "gateway-credentials")) {
+ bind_cred = val;
+ } else if (!strcasecmp(var, "auth-scheme")) {
+ if (*val == '=') {
+ auth_scheme = 0;
+ val++;
+ }
+
+ if (!strcasecmp(val, "basic")) {
+ auth_scheme |= CURLAUTH_BASIC;
+ } else if (!strcasecmp(val, "digest")) {
+ auth_scheme |= CURLAUTH_DIGEST;
+ } else if (!strcasecmp(val, "NTLM")) {
+ auth_scheme |= CURLAUTH_NTLM;
+ } else if (!strcasecmp(val, "GSS-NEGOTIATE")) {
+ auth_scheme |= CURLAUTH_GSSNEGOTIATE;
+ } else if (!strcasecmp(val, "any")) {
+ auth_scheme = CURLAUTH_ANY;
+ }
+ } else if (!strcasecmp(var, "disable-100-continue") && !switch_true(val)) {
+ disable100continue = 0;
+ } else if (!strcasecmp(var, "method")) {
+ method = val;
+ } else if (!strcasecmp(var, "timeout")) {
+ int tmp = atoi(val);
+ if (tmp >= 0) {
+ timeout = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
+ }
+ } else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
+ enable_cacert_check = 1;
+ } else if (!strcasecmp(var, "ssl-cert-path")) {
+ ssl_cert_file = val;
+ } else if (!strcasecmp(var, "ssl-key-path")) {
+ ssl_key_file = val;
+ } else if (!strcasecmp(var, "ssl-key-password")) {
+ ssl_key_password = val;
+ } else if (!strcasecmp(var, "ssl-version")) {
+ ssl_version = val;
+ } else if (!strcasecmp(var, "ssl-cacert-file")) {
+ ssl_cacert_file = val;
+ } else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) {
+ enable_ssl_verifyhost = 1;
+ } else if (!strcasecmp(var, "cookie-file")) {
+ cookie_file = val;
+ } else if (!strcasecmp(var, "enable-post-var")) {
+ if (!vars_map && need_vars_map == 0) {
+ if (switch_core_hash_init(&vars_map, globals.pool) != SWITCH_STATUS_SUCCESS) {
+ need_vars_map = -1;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't init params hash!\n");
+ continue;
+ }
+ need_vars_map = 1;
+ }
+
+ if (vars_map && val) {
+ if (switch_core_hash_insert(vars_map, val, ENABLE_PARAM_VALUE) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't add %s to params hash!\n", val);
+ }
+ }
+ } else if (!strcasecmp(var, "bind-local")) {
+ bind_local = val;
+ }
+ }
+ }
+
+ if (!url) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile has no url!\n");
+ if (vars_map)
+ switch_core_hash_destroy(&vars_map);
+ continue;
+ }
+
+ if (!(profile = switch_core_alloc(globals.pool, sizeof(*profile)))) {
+ if (vars_map)
+ switch_core_hash_destroy(&vars_map);
+ goto done;
+ }
+ memset(profile, 0, sizeof(*profile));
+
+
+ /* Defaults */
+ profile->ua = ua;
+ profile->conference_params.use_profile = "default";
+ profile->perms.set_params = 1;
+ profile->perms.conference.enabled = 1;
+ profile->perms.dial.enabled = 1;
+
+
+ if ((tag = switch_xml_child(profile_tag, "conference"))) {
+ for (param = switch_xml_child(tag, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "default-profile")) {
+ profile->conference_params.use_profile = switch_core_strdup(globals.pool, val);
+ }
+ }
+ }
+
+ if ((tag = switch_xml_child(profile_tag, "dial"))) {
+ for (param = switch_xml_child(tag, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "context")) {
+ profile->dial_params.context = switch_core_strdup(globals.pool, val);
+ } else if (!strcasecmp(var, "dialplan")) {
+ profile->dial_params.dp = switch_core_strdup(globals.pool, val);
+ }
+ }
+ }
+
+ if ((tag = switch_xml_child(profile_tag, "permissions"))) {
+ for (param = switch_xml_child(tag, "permission"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "all")) {
+ switch_byte_t all = switch_true(val);
+ memset(&profile->perms, all, sizeof(profile->perms));
+ } else if (!strcasecmp(var, "none")) {
+ switch_byte_t none = switch_true(val);
+ memset(&profile->perms, none, sizeof(profile->perms));
+ } else if (!strcasecmp(var, "set-params")) {
+ profile->perms.set_params = switch_true(val);
+ } else if (!strcasecmp(var, "set-vars")) {
+ profile->perms.set_vars = switch_true(val);
+
+ if (profile->perms.set_vars) {
+ switch_xml_t x_list, x_var;
+ if ((x_list = switch_xml_child(param, "variable-list"))) {
+ char *var = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
+ switch_event_create(&profile->var_params.set_var_list, SWITCH_EVENT_CLONE);
+ profile->var_params.set_var_list->flags |= EF_UNIQ_HEADERS;
+ if (profile->var_params.default_allow) {
+ profile->var_params.set_var_list->flags |= EF_DEFAULT_ALLOW;
+ }
+
+
+ for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
+ const char *name = switch_xml_attr(x_var, "name");
+ const char *type = switch_xml_attr(x_var, "type");
+
+ if (zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->var_params.set_var_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+ }
+ } else if (!strcasecmp(var, "get-vars")) {
+ profile->perms.get_vars = switch_true(val);
+
+ if (profile->perms.get_vars) {
+ switch_xml_t x_list, x_var;
+ if ((x_list = switch_xml_child(param, "variable-list"))) {
+ char *var = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
+ switch_event_create(&profile->var_params.get_var_list, SWITCH_EVENT_CLONE);
+ profile->var_params.get_var_list->flags |= EF_UNIQ_HEADERS;
+ if (profile->var_params.default_allow) {
+ profile->var_params.get_var_list->flags |= EF_DEFAULT_ALLOW;
+ }
+
+
+ for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
+ const char *name = switch_xml_attr(x_var, "name");
+ const char *type = switch_xml_attr(x_var, "type");
+
+ if (zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->var_params.get_var_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+ }
+ } else if (!strcasecmp(var, "extended-data")) {
+ profile->perms.extended_data = switch_true(val);
+ } else if (!strcasecmp(var, "execute-apps")) {
+ profile->perms.execute_apps = switch_true(val);
+
+ if (profile->perms.execute_apps) {
+ switch_xml_t x_list, x_app;
+ if ((x_list = switch_xml_child(param, "application-list"))) {
+ char *var = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->dial_params.default_allow = (var && !strcasecmp(var, "allow"));
+ switch_event_create(&profile->dial_params.app_list, SWITCH_EVENT_CLONE);
+ profile->dial_params.app_list->flags |= EF_UNIQ_HEADERS;
+ if (profile->dial_params.default_allow) {
+ profile->dial_params.app_list->flags |= EF_DEFAULT_ALLOW;
+ }
+
+
+ for (x_app = switch_xml_child(x_list, "application"); x_app; x_app = x_app->next) {
+ const char *name = switch_xml_attr(x_app, "name");
+ const char *type = switch_xml_attr(x_app, "type");
+
+ if (zstr(type)) type = profile->dial_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->dial_params.app_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+ }
+
+ } else if (!strcasecmp(var, "expand-vars")) {
+ profile->perms.expand_vars = switch_true(val);
+
+ if (profile->perms.expand_vars) {
+ switch_xml_t x_list, x_var, x_api;
+ if ((x_list = switch_xml_child(param, "variable-list"))) {
+ char *var = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->var_params.default_allow = (var && !strcasecmp(var, "allow"));
+ switch_event_create(&profile->var_params.expand_var_list, SWITCH_EVENT_CLONE);
+ profile->var_params.expand_var_list->flags |= EF_UNIQ_HEADERS;
+ if (profile->var_params.default_allow) {
+ profile->var_params.expand_var_list->flags |= EF_DEFAULT_ALLOW;
+ }
+
+
+ for (x_var = switch_xml_child(x_list, "variable"); x_var; x_var = x_var->next) {
+ const char *name = switch_xml_attr(x_var, "name");
+ const char *type = switch_xml_attr(x_var, "type");
+
+ if (zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->var_params.expand_var_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+
+ if ((x_list = switch_xml_child(param, "api-list"))) {
+ char *api = (char *) switch_xml_attr_soft(param, "default");
+
+ profile->var_params.default_allow = (api && !strcasecmp(api, "allow"));
+ switch_event_create(&profile->var_params.api_list, SWITCH_EVENT_CLONE);
+ profile->var_params.api_list->flags |= EF_UNIQ_HEADERS;
+ if (profile->var_params.default_allow) {
+ profile->var_params.api_list->flags |= EF_DEFAULT_ALLOW;
+ }
+
+
+ for (x_api = switch_xml_child(x_list, "api"); x_api; x_api = x_api->next) {
+ const char *name = switch_xml_attr(x_api, "name");
+ const char *type = switch_xml_attr(x_api, "type");
+
+ if (zstr(type)) type = profile->var_params.default_allow ? "deny" : "allow";
+
+ if (name) {
+ switch_event_add_header_string(profile->var_params.api_list, SWITCH_STACK_BOTTOM, name, type);
+ }
+ }
+ }
+ }
+
+ } else if (!strcasecmp(var, "dial")) {
+ profile->perms.dial.enabled = switch_true(val);
+ } else if (!strcasecmp(var, "dial-set-context")) {
+ profile->perms.dial.enabled = switch_true(val);
+ profile->perms.dial.set_context = switch_true(val);
+ } else if (!strcasecmp(var, "dial-set-dialplan")) {
+ profile->perms.dial.enabled = switch_true(val);
+ profile->perms.dial.set_dp = switch_true(val);
+ } else if (!strcasecmp(var, "dial-set-cid-name")) {
+ profile->perms.dial.enabled = switch_true(val);
+ profile->perms.dial.set_cid_name = switch_true(val);
+ } else if (!strcasecmp(var, "dial-set-cid-number")) {
+ profile->perms.dial.enabled = switch_true(val);
+ profile->perms.dial.set_cid_number = switch_true(val);
+ } else if (!strcasecmp(var, "dial-full-originate")) {
+ profile->perms.dial.enabled = switch_true(val);
+ profile->perms.dial.full_originate = switch_true(val);
+ } else if (!strcasecmp(var, "conference")) {
+ profile->perms.conference.enabled = switch_true(val);
+ } else if (!strcasecmp(var, "conference-set-profile")) {
+ profile->perms.conference.enabled = switch_true(val);
+ profile->perms.conference.set_profile = switch_true(val);
+ }
+
+ }
+ }
+
+
+
+ profile->auth_scheme = auth_scheme;
+ profile->timeout = timeout;
+ profile->url = strdup(url);
+ switch_assert(profile->url);
+
+ if (bind_local != NULL) {
+ profile->bind_local = strdup(bind_local);
+ }
+ if (method != NULL) {
+ profile->method = strdup(method);
+ } else {
+ profile->method = NULL;
+ }
+
+ if (bind_cred) {
+ profile->cred = strdup(bind_cred);
+ }
+
+ profile->disable100continue = disable100continue;
+ profile->enable_cacert_check = enable_cacert_check;
+
+ if (ssl_cert_file) {
+ profile->ssl_cert_file = strdup(ssl_cert_file);
+ }
+
+ if (ssl_key_file) {
+ profile->ssl_key_file = strdup(ssl_key_file);
+ }
+
+ if (ssl_key_password) {
+ profile->ssl_key_password = strdup(ssl_key_password);
+ }
+
+ if (ssl_version) {
+ profile->ssl_version = strdup(ssl_version);
+ }
+
+ if (ssl_cacert_file) {
+ profile->ssl_cacert_file = strdup(ssl_cacert_file);
+ }
+
+ profile->enable_ssl_verifyhost = enable_ssl_verifyhost;
+
+ if (cookie_file) {
+ profile->cookie_file = strdup(cookie_file);
+ }
+
+ profile->vars_map = vars_map;
+
+ if (vars_map) {
+ switch_zmalloc(hash_node, sizeof(hash_node_t));
+ hash_node->hash = vars_map;
+ hash_node->next = NULL;
+
+ if (!globals.hash_root) {
+ globals.hash_root = hash_node;
+ globals.hash_tail = globals.hash_root;
+ }
+
+ else {
+ globals.hash_tail->next = hash_node;
+ globals.hash_tail = globals.hash_tail->next;
+ }
+
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Profile [%s] JSON Function [%s]\n",
+ zstr(bname) ? "N/A" : bname, profile->url);
+
+ profile->name = strdup(bname);
+
+ switch_core_hash_insert(globals.profile_hash, bname, profile);
+
+ x++;
+ profile = NULL;
+ }
+
+ done:
+
+ switch_xml_free(xml);
+
+ return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t my_on_reporting(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ client_t *client;
+ const char *var;
+
+ if (!(client = (client_t *) switch_channel_get_private(channel, "_HTTAPI_CLIENT_"))) {
+ return status;
+ }
+
+ switch_channel_set_private(channel, "_HTTAPI_CLIENT_", NULL);
+
+ if (client->profile->perms.extended_data) {
+ switch_channel_event_set_extended_data(channel, client->one_time_params);
+ }
+
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "exiting", "true");
+
+ if (client->record.file) {
+ char *key = switch_core_sprintf(client->pool, "attach_file:%s:%s.wav", client->record.name, switch_core_session_get_uuid(session));
+ switch_ivr_stop_record_session(client->session, client->record.file);
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, key, client->record.file);
+ }
+
+ var = switch_event_get_header(client->params, "url");
+
+ if (client->record.action) {
+ if (strcmp(var, client->record.action)) {
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "url", client->record.action);
+ httapi_sync(client);
+ if (client->profile->perms.extended_data) {
+ switch_channel_event_set_extended_data(channel, client->one_time_params);
+ }
+ switch_event_add_header_string(client->one_time_params, SWITCH_STACK_BOTTOM, "exiting", "true");
+ }
+ }
+
+ httapi_sync(client);
+
+ client_destroy(&client);
+
+ return status;
+}
+
+static switch_state_handler_table_t state_handlers = {
+ /*.on_init */ NULL,
+ /*.on_routing */ NULL,
+ /*.on_execute */ NULL,
+ /*.on_hangup */ NULL,
+ /*.on_exchange_media */ NULL,
+ /*.on_soft_execute */ NULL,
+ /*.on_consume_media */ NULL,
+ /*.on_hibernate */ NULL,
+ /*.on_reset */ NULL,
+ /*.on_park */ NULL,
+ /*.on_reporting */ my_on_reporting,
+ /*.on_destroy */ NULL,
+ SSH_FLAG_STICKY
+};
+
+
+SWITCH_STANDARD_APP(httapi_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ char *parsed = NULL;
+ const char *profile_name = NULL, *url = NULL;
+ client_t *client;
+ switch_event_t *params = NULL;
+ uint32_t loops = 0, all_extended = 0;
+ switch_caller_profile_t *caller_profile;
+
+ if (!zstr(data)) {
+ switch_event_create_brackets((char *)data, '{', '}', ',', ¶ms, &parsed, SWITCH_TRUE);
+
+ if (params) {
+ url = parsed;
+ } else {
+ url = data;
+ }
+
+ if (!zstr(url) && switch_stristr("://", url)) {
+ if (!params) {
+ switch_event_create(¶ms, SWITCH_EVENT_CLONE);
+ }
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "url", url);
+ }
+ }
+
+ if ((client = (client_t *) switch_channel_get_private(channel, "_HTTAPI_CLIENT_"))) {
+ if (params) {
+ switch_event_merge(client->params, params);
+ switch_event_destroy(¶ms);
+ }
+ } else {
+ if (params) {
+ profile_name = switch_event_get_header(params, "httapi_profile");
+ }
+
+ if (zstr(profile_name) && !(profile_name = switch_channel_get_variable(channel, "httapi_profile"))) {
+ profile_name = "default";
+ }
+
+ if ((client = client_create(session, profile_name, ¶ms))) {
+ switch_channel_set_private(channel, "_HTTAPI_CLIENT_", client);
+ switch_channel_add_state_handler(channel, &state_handlers);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find suitable profile\n");
+ switch_event_destroy(¶ms);
+ return;
+ }
+ }
+
+ if (client->profile->perms.extended_data) {
+ all_extended = switch_true(switch_event_get_header(client->params, "full_channel_data_on_every_req"));
+ }
+
+ if ((caller_profile = switch_channel_get_caller_profile(channel))) {
+ switch_caller_profile_event_set_data(caller_profile, "Caller", client->params);
+ }
+
+ while(switch_channel_ready(channel)) {
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (client->profile->perms.extended_data && (!loops++ || all_extended)) {
+ switch_channel_event_set_extended_data(channel, client->one_time_params);
+ }
+
+ if ((status = httapi_sync(client)) == SWITCH_STATUS_SUCCESS) {
+ if (client->code == 200) {
+ const char *ct = switch_event_get_header(client->headers, "content-type");
+
+ if (switch_stristr("text/xml", ct)) {
+ status = parse_xml(client);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received unsupported content-type %s\n", ct);
+ break;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received HTTP response: %ld.\n", client->code);
+ break;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %d!\n", client->err);
+ }
+
+ if (status == SWITCH_STATUS_TERM) {
+ httapi_sync(client);
+ }
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ }
+
+
+ switch_safe_free(parsed);
+
+}
+
+
+/* HTTP FILE INTERFACE */
+
+static char *load_cache_data(http_file_context_t *context, const char *url)
+{
+ char *ext = NULL;
+ char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };
+ char meta_buffer[1024] = "";
+ int fd;
+ switch_ssize_t bytes;
+
+ switch_md5_string(digest, (void *) url, strlen(url));
+
+ if (context->url_params) {
+ ext = switch_event_get_header(context->url_params, "ext");
+ }
+
+ if (zstr(ext)) {
+ if ((ext = strrchr(url, '.'))) {
+ ext++;
+ } else {
+ ext = "wav";
+ }
+ }
+
+ context->cache_file = switch_core_sprintf(context->pool, "%s%s%s.%s", globals.cache_path, SWITCH_PATH_SEPARATOR, digest, ext);
+ context->meta_file = switch_core_sprintf(context->pool, "%s.meta", context->cache_file);
+ context->lock_file = switch_core_sprintf(context->pool, "%s.lock", context->cache_file);
+
+ if (switch_file_exists(context->meta_file, context->pool) == SWITCH_STATUS_SUCCESS && ((fd = open(context->meta_file, O_RDONLY, 0)) > -1)) {
+ if ((bytes = read(fd, meta_buffer, sizeof(meta_buffer))) > 0) {
+ char *p;
+
+ if ((p = strchr(meta_buffer, ':'))) {
+ *p++ = '\0';
+ context->expires = (time_t) atol(meta_buffer);
+ context->metadata = switch_core_strdup(context->pool, p);
+ }
+ }
+ close(fd);
+ }
+
+ return context->cache_file;
+}
+
+static size_t save_file_callback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+ register unsigned int realsize = (unsigned int) (size * nmemb);
+ client_t *client = data;
+ int x;
+
+ client->bytes += realsize;
+
+
+
+ if (client->bytes > client->max_bytes) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) client->bytes);
+ client->err = 1;
+ return 0;
+ }
+
+ x = write(client->fd, ptr, realsize);
+
+ if (x != (int) realsize) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Short write! %d out of %d\n", x, realsize);
+ }
+ return x;
+}
+
+
+
+static switch_status_t fetch_cache_data(http_file_context_t *context, const char *url, switch_event_t **headers, const char *save_path)
+{
+ switch_CURL *curl_handle = NULL;
+ client_t client = { 0 };
+ long code;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ char *dup_creds = NULL, *dynamic_url = NULL, *use_url;
+ char *ua = NULL;
+
+ client.fd = -1;
+
+ if (save_path) {
+ if ((client.fd = open(save_path, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ if (context->url_params) {
+ ua = switch_event_get_header(context->url_params, "user_agent");
+ }
+
+ if (zstr(ua)) {
+ ua = "mod_httapi/1.0";
+ }
+
+ if ((use_url = strchr(url, '@'))) {
+ char *r, *q, *p = strstr(url, "://");
+ use_url++;
+
+ dup_creds = strdup(p+3);
+
+ if ((q = strchr(dup_creds, '@'))) *q = '\0';
+
+ q = strdup(url);
+ r = strchr(q, '@');
+ r++;
+
+ if ((p = strstr(q, "://"))) {
+ *(p+3) = '\0';
+ }
+
+ p = switch_mprintf("%s%s", q, r);
+ dynamic_url = p;
+ free(q);
+ url = dynamic_url;
+ }
+
+ curl_handle = switch_curl_easy_init();
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
+
+ if (!strncasecmp(url, "https", 5)) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+
+ client.max_bytes = HTTAPI_MAX_FILE_BYTES;
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
+
+ if (save_path) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, save_file_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &client);
+ } else {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1);
+ }
+
+ if (headers) {
+ switch_event_create(&client.headers, SWITCH_EVENT_CLONE);
+ if (save_path) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, get_header_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, (void *) &client);
+ } else {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, get_header_callback);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &client);
+ }
+ }
+
+ if (!zstr(dup_creds)) {
+ switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, dup_creds);
+ }
+
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, ua);
+ switch_curl_easy_perform(curl_handle);
+ switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &code);
+ switch_curl_easy_cleanup(curl_handle);
+
+ if (client.fd > -1) {
+ close(client.fd);
+ }
+
+ if (headers && client.headers) {
+ switch_event_add_header(client.headers, SWITCH_STACK_BOTTOM, "http-response-code", "%ld", code);
+ *headers = client.headers;
+ }
+
+ switch(code) {
+ case 200:
+ if (save_path) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "caching: url:%s to %s (%" SWITCH_SIZE_T_FMT " bytes)\n", url, save_path, client.bytes);
+ }
+ status = SWITCH_STATUS_SUCCESS;
+ break;
+
+ case 404:
+ status = SWITCH_STATUS_NOTFOUND;
+ break;
+
+ default:
+ status = SWITCH_STATUS_FALSE;
+ break;
+ }
+
+ switch_safe_free(dynamic_url);
+ switch_safe_free(dup_creds);
+
+
+ return status;
+}
+
+static switch_status_t write_meta_file(http_file_context_t *context, const char *data, switch_event_t *headers)
+{
+ int fd;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char write_data[1024];
+
+ if ((fd = open(context->meta_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!zstr(data)) {
+ int ttl = globals.cache_ttl;
+ const char *cc;
+ const char *p;
+
+ if (headers && (cc = switch_event_get_header(headers, "Cache-Control"))) {
+ if ((p = switch_stristr("max-age=", cc))) {
+ p += 8;
+
+ if (!zstr(p)) {
+ ttl = atoi(p);
+ if (ttl < 0) ttl = globals.cache_ttl;
+ }
+ }
+
+ if (switch_stristr("no-cache", cc) || switch_stristr("no-store", cc)) {
+ context->del_on_close = 1;
+ }
+ }
+
+ switch_snprintf(write_data, sizeof(write_data),
+ "%" SWITCH_TIME_T_FMT ":%s",
+ switch_epoch_time_now(NULL) + ttl,
+ data);
+
+
+ status = write(fd, write_data, strlen(write_data) + 1) > 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
+ }
+
+ close(fd);
+
+ return status;
+}
+
+
+static switch_status_t lock_file(http_file_context_t *context, switch_bool_t lock)
+{
+
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+
+ if (lock) {
+ if (switch_file_open(&context->lock_fd,
+ context->lock_file,
+ SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE | SWITCH_FOPEN_TRUNCATE,
+ SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, context->pool) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+ if (switch_file_lock(context->lock_fd, SWITCH_FLOCK_EXCLUSIVE) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+ } else {
+ if (context->lock_fd){
+ switch_file_close(context->lock_fd);
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ unlink(context->lock_file);
+ }
+
+ return status;
+}
+
+
+static switch_status_t locate_url_file(http_file_context_t *context, const char *url)
+{
+ switch_event_t *headers = NULL;
+ int unreachable = 0;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ time_t now = switch_epoch_time_now(NULL);
+ char *metadata;
+
+ load_cache_data(context, url);
+
+ if (context->expires && now < context->expires) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ lock_file(context, SWITCH_TRUE);
+
+ if ((status = fetch_cache_data(context, url, &headers, NULL)) != SWITCH_STATUS_SUCCESS) {
+ if (status == SWITCH_STATUS_NOTFOUND) {
+ unreachable = 2;
+ if (now - context->expires < globals.not_found_expires) {
+ switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+ }
+ } else {
+ unreachable = 1;
+ }
+ }
+
+ if (switch_file_exists(context->cache_file, context->pool) != SWITCH_STATUS_SUCCESS && unreachable) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File at url [%s] is unreachable!\n", url);
+ goto end;
+ }
+
+ if (!unreachable && !zstr(context->metadata)) {
+ metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s",
+ url,
+ switch_event_get_header_nil(headers, "last-modified"),
+ switch_event_get_header_nil(headers, "etag"),
+ switch_event_get_header_nil(headers, "content-length")
+ );
+
+ if (!strcmp(metadata, context->metadata)) {
+ write_meta_file(context, metadata, headers);
+ switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+ }
+ }
+
+ switch_event_destroy(&headers);
+ fetch_cache_data(context, url, &headers, context->cache_file);
+ metadata = switch_core_sprintf(context->pool, "%s:%s:%s:%s",
+ url,
+ switch_event_get_header_nil(headers, "last-modified"),
+ switch_event_get_header_nil(headers, "etag"),
+ switch_event_get_header_nil(headers, "content-length")
+ );
+
+ write_meta_file(context, metadata, headers);
+
+ if (switch_file_exists(context->cache_file, context->pool) == SWITCH_STATUS_SUCCESS) {
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ end:
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ unlink(context->meta_file);
+ unlink(context->cache_file);
+ }
+
+ lock_file(context, SWITCH_FALSE);
+
+ switch_event_destroy(&headers);
+
+ return status;
+}
+
+
+static switch_status_t http_file_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
+{
+ http_file_context_t *context = handle->private_info;
+
+ if (!handle->seekable) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File is not seekable\n");
+ return SWITCH_STATUS_NOTIMPL;
+ }
+
+ return switch_core_file_seek(&context->fh, cur_sample, samples, whence);
+}
+
+static switch_status_t http_file_file_open(switch_file_handle_t *handle, const char *path)
+{
+ http_file_context_t *context;
+ char *parsed = NULL, *pdup = NULL;
+ switch_status_t status;
+
+ context = switch_core_alloc(handle->memory_pool, sizeof(*context));
+ context->pool = handle->memory_pool;
+
+ pdup = switch_core_strdup(context->pool, path);
+
+ switch_event_create_brackets(pdup, '(', ')', ',', &context->url_params, &parsed, SWITCH_FALSE);
+
+ if (context->url_params) {
+ context->ua = switch_event_get_header(context->url_params, "ua");
+ }
+
+ if (parsed) path = parsed;
+
+ context->dest_url = switch_core_sprintf(context->pool, "http://%s", path);
+
+ if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
+ char *ext;
+
+ context->fh.channels = handle->channels;
+ context->fh.native_rate = handle->native_rate;
+ context->fh.samples = handle->samples;
+ context->fh.samplerate = handle->samplerate;
+ context->fh.prefix = handle->prefix;
+
+
+ if (context->url_params) {
+ context->write.file_name = switch_event_get_header(context->url_params, "file");
+ context->write.profile_name = switch_event_get_header(context->url_params, "profile");
+ context->write.method = switch_event_get_header(context->url_params, "method");
+ context->write.name = switch_event_get_header(context->url_params, "name");
+ }
+
+ if (!context->write.file_name) {
+ char *p;
+ if ((p = strrchr(context->dest_url, '/'))) {
+ p++;
+ context->write.file_name = switch_core_strdup(context->pool, p);
+ }
+ }
+
+ if ((ext = strrchr(context->write.file_name, '.'))) {
+ ext++;
+ } else {
+ ext = "wav";
+ }
+
+ if (!context->write.profile_name) context->write.profile_name = "default";
+ if (!context->write.method) context->write.method = !strcasecmp(ext, "cgi") ? "post" : "put";
+ if (!context->write.name) context->write.name = "recorded_file";
+
+ switch_uuid_str(context->write.uuid_str, sizeof(context->write.uuid_str));
+
+ context->write.file = switch_core_sprintf(context->pool, "%s%s%s_%s",
+ SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, context->write.uuid_str, context->write.file_name);
+
+
+ if (switch_core_file_open(&context->fh, context->write.file, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ } else {
+
+ if (context->url_params) {
+ context->read.ext = switch_event_get_header(context->url_params, "ext");
+ }
+
+ if ((status = locate_url_file(context, context->dest_url)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+
+ if ((status = switch_core_file_open(&context->fh,
+ context->cache_file,
+ handle->channels,
+ handle->samplerate,
+ SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid cache file %s opening url %s Discarding file.\n", context->cache_file, path);
+ unlink(context->cache_file);
+ unlink(context->meta_file);
+ unlink(context->lock_file);
+
+ return status;
+ }
+ }
+
+ handle->private_info = context;
+ handle->samples = context->fh.samples;
+ handle->format = context->fh.format;
+ handle->sections = context->fh.sections;
+ handle->seekable = context->fh.seekable;
+ handle->speed = context->fh.speed;
+ handle->interval = context->fh.interval;
+
+ if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
+ switch_set_flag(handle, SWITCH_FILE_NATIVE);
+ } else {
+ switch_clear_flag(handle, SWITCH_FILE_NATIVE);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t http_file_file_close(switch_file_handle_t *handle)
+{
+ http_file_context_t *context = handle->private_info;
+
+ if (switch_test_flag((&context->fh), SWITCH_FILE_OPEN)) {
+ switch_core_file_close(&context->fh);
+ }
+
+ if (context->write.file) {
+ client_t *client;
+ switch_event_t *params;
+ char *key;
+
+ switch_event_create(¶ms, SWITCH_EVENT_CLONE);
+ params->flags |= EF_UNIQ_HEADERS;
+
+ if (!strcasecmp(context->write.method, "put")) {
+ switch_event_add_header(params, SWITCH_STACK_BOTTOM, "put_file", "%s", context->write.file);
+ } else {
+ key = switch_core_sprintf(context->pool, "attach_file:%s:%s", context->write.name, context->write.file_name);
+ switch_event_add_header(params, SWITCH_STACK_BOTTOM, key, "%s", context->write.file);
+ }
+
+ switch_event_add_header(params, SWITCH_STACK_BOTTOM, "url", "%s", context->dest_url);
+ switch_event_add_header(params, SWITCH_STACK_BOTTOM, "file_driver", "true");
+ switch_event_add_header(params, SWITCH_STACK_BOTTOM, "HTTAPI_SESSION_ID", "%s", context->write.uuid_str);
+
+ if ((client = client_create(NULL, context->write.profile_name, ¶ms))) {
+ httapi_sync(client);
+ client_destroy(&client);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find suitable profile\n");
+ switch_event_destroy(¶ms);
+ }
+
+ unlink(context->write.file);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+
+ if (context->del_on_close) {
+ if (context->cache_file) {
+ unlink(context->cache_file);
+ unlink(context->meta_file);
+ unlink(context->lock_file);
+ }
+ }
+
+ if (context->url_params) {
+ switch_event_destroy(&context->url_params);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+static switch_status_t http_file_write(switch_file_handle_t *handle, void *data, size_t *len)
+{
+ http_file_context_t *context = handle->private_info;
+
+ return switch_core_file_write(&context->fh, data, len);
+}
+
+static switch_status_t http_file_file_read(switch_file_handle_t *handle, void *data, size_t *len)
+{
+ http_file_context_t *context = handle->private_info;
+ switch_status_t status;
+
+ if (context->samples > 0) {
+ if (*len > (size_t) context->samples) {
+ *len = context->samples;
+ }
+
+ context->samples -= *len;
+ memset(data, 255, *len *2);
+ status = SWITCH_STATUS_SUCCESS;
+ } else {
+ status = switch_core_file_read(&context->fh, data, len);
+ }
+
+ return status;
+}
+
+/* Registration */
+
+static char *http_file_supported_formats[SWITCH_MAX_CODECS] = { 0 };
+
+
+/* /HTTP FILE INTERFACE */
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_httapi_load)
+{
+ switch_api_interface_t *httapi_api_interface;
+ switch_application_interface_t *app_interface;
+ switch_file_interface_t *file_interface;
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ memset(&globals, 0, sizeof(globals));
+ globals.pool = pool;
+ globals.hash_root = NULL;
+ globals.hash_tail = NULL;
+ globals.cache_ttl = 300;
+ globals.not_found_expires = 300;
+
+
+ http_file_supported_formats[0] = "http";
+
+ file_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
+ file_interface->interface_name = modname;
+ file_interface->extens = http_file_supported_formats;
+ file_interface->file_open = http_file_file_open;
+ file_interface->file_close = http_file_file_close;
+ file_interface->file_read = http_file_file_read;
+ file_interface->file_write = http_file_write;
+ file_interface->file_seek = http_file_file_seek;
+
+ switch_snprintf(globals.cache_path, sizeof(globals.cache_path), "%s%shttp_file_cache", SWITCH_GLOBAL_dirs.storage_dir, SWITCH_PATH_SEPARATOR);
+ switch_dir_make_recursive(globals.cache_path, SWITCH_DEFAULT_DIR_PERMS, pool);
+
+
+ switch_core_hash_init(&globals.profile_hash, globals.pool);
+ switch_core_hash_init_case(&globals.parse_hash, globals.pool, SWITCH_FALSE);
+
+ bind_parser("execute", parse_execute);
+ bind_parser("sms", parse_sms);
+ bind_parser("dial", parse_dial);
+ bind_parser("pause", parse_playback);
+ bind_parser("hangup", parse_hangup);
+ bind_parser("record", parse_record);
+ bind_parser("recordCall", parse_record_call);
+ bind_parser("playback", parse_playback);
+ bind_parser("speak", parse_playback);
+ bind_parser("say", parse_playback);
+ bind_parser("conference", parse_conference);
+ bind_parser("break", parse_break);
+ bind_parser("log", parse_log);
+ bind_parser("continue", parse_continue);
+ bind_parser("getVariable", parse_get_var);
+ bind_parser("voicemail", parse_voicemail);
+
+ if (do_config() != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ SWITCH_ADD_API(httapi_api_interface, "httapi",
+ "HT-TAPI Hypertext Telephony API", httapi_api_function, HTTAPI_SYNTAX);
+
+ SWITCH_ADD_APP(app_interface, "httapi",
+ "HT-TAPI Hypertext Telephony API",
+ "HT-TAPI Hypertext Telephony API", httapi_function, "{=}", SAF_SUPPORT_NOMEDIA);
+
+
+
+ switch_console_set_complete("add httapi debug_on");
+ switch_console_set_complete("add httapi debug_off");
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_httapi_shutdown)
+{
+ hash_node_t *ptr = NULL;
+ client_profile_t *profile;
+ switch_hash_index_t *hi;
+ void *val;
+ const void *vvar;
+
+ for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &val);
+ profile = (client_profile_t *) val;
+ switch_event_destroy(&profile->dial_params.app_list);
+ switch_event_destroy(&profile->var_params.expand_var_list);
+ switch_event_destroy(&profile->var_params.set_var_list);
+ switch_event_destroy(&profile->var_params.get_var_list);
+ }
+
+
+ switch_core_hash_destroy(&globals.profile_hash);
+ switch_core_hash_destroy(&globals.parse_hash);
+
+ while (globals.hash_root) {
+ ptr = globals.hash_root;
+ switch_core_hash_destroy(&ptr->hash);
+ globals.hash_root = ptr->next;
+ switch_safe_free(ptr);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+
+
diff --git a/src/mod/applications/mod_httapi/mod_httapi_doc.txt b/src/mod/applications/mod_httapi/mod_httapi_doc.txt
new file mode 100644
index 0000000000..e8bf9bf9bc
--- /dev/null
+++ b/src/mod/applications/mod_httapi/mod_httapi_doc.txt
@@ -0,0 +1,325 @@
+HT-TAPI Hyper-Text Telephony API and http file format plugin
+
+This module provides an HTTP based Telephony API using a standard FreeSWITCH application interface as well as a cached http file format interface.
+
+The file format plugin can be used like this:
+
+
+This syntax is valid anywhere a filename parameter is requested in FreeSWITCH.
+
+
+The application is called like this:
+
+
+
+The target url is expected to be a CGI returning text/xml using the documentation below.
+
+The format is roughly as described below (We could use a DTD maybe).
+
+
+
+ someval
+
+
+ someval
+
+
+ <...>
+
+
+
+
+The profile name must be chosen to bind to a preset series of settings and permissions to use as a basis for the client session.
+It's chosen from the specified params or from the channel variable using the keyname 'httapi_profile' and if not specified will default to 'default'
+Any params specified in the initial data of the application encased in brackets {} will be parsed into the initial params similar to originate.
+These params remain set until the call ends and are supplied as form elements on each hit to the HTTP server.
+If the permissions allow, a tag is parsed from the resulting document and set into this data set and will be mirrored back on subsequqent http posts.
+Also if the permissions allow a tag is parsed the same way setting channel variables.
+The tag is required and contains one or more of the supported command tags that generally manipulate the call behaviour.
+The application will continue to do the task in the work section until an error is encoutered or when an action from the work tag warrants it.
+If the session exits the httapi app without hanging up it can do other tasks and make another call to httapi and the session data will remain preserved.
+
+
+EXAMPLE:
+
+
+
+
+
+~\d+#
+
+
+
+
+BINDINGS
+Several of the work tags that indicate they support bindings can contain one of more bind tags that function with similar fashion to bind_digit_action
+
+*EXPR*
+
+ATTRS:
+action : a specific url to go to next if the binding is dialed
+strip : a character to strip from in the result such as #
+
+WORK TAGS:
+*ACTIONS*
+
+
+*EXPR*
+ : Plays a file and optionally collects input.
+
+ATTRS:
+file : The file
+name : Param name to save result.
+error-file : Error file to play on invalid input.
+action : Change the new target url.
+temp-action : Change url to submit to. just for the next loop.
+digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
+input-timeout : Timeout waiting for more digits in a multi-digit input.
+loops : max times to play the file when input bindings are present.
+asr-engine : ASR engine to use
+asr-grammar : ASR grammar to use
+
+
+
+
+*EXPR*
+ : Records a file, optionally collects input and posts the file back to the target url.
+
+ATTRS:
+file : The file
+name : Param name to save result.
+error-file : Error file to play on invalid input.
+action : Change the new target url.
+temp-action : Change url to submit to. just for the next loop.
+digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
+input-timeout : Timeout waiting for more digits in a multi-digit input.
+
+
+
+
+
+*EXPR*
+ : Waits for input for a specific amount of time.
+
+ATTRS:
+milliseconds : Number of milliseconds to pause
+name : Param name to save result.
+error-file : Error file to play on invalid input.
+action : Change the new target url.
+temp-action : Change url to submit to. just for the next loop.
+digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
+input-timeout : Timeout waiting for more digits in a multi-digit input.
+loops : max times to play the file when input bindings are present.
+
+
+
+
+
+*EXPR*
+ : Read Text to Speech with optional input.
+
+ATTRS:
+file : The file
+name : Param name to save result.
+error-file : Error file to play on invalid input.
+action : Change the new target url.
+temp-action : Change url to submit to. just for the next loop.
+digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
+input-timeout : Timeout waiting for more digits in a multi-digit input.
+loops : max times to play the file when input bindings are present.
+engine : tts engine to use.
+voice : tts voice to use.
+
+
+
+
+
+*EXPR*
+ : Use the FS say engine to iterate sounds to similate a human speaker.
+
+ATTRS:
+file : The file
+name : Param name to save result.
+error-file : Error file to play on invalid input.
+action : Change the new target url.
+temp-action : Change url to submit to. just for the next loop.
+digit-timeout : Timeout waiting for digits after file plays (when input bindings are present)
+input-timeout : Timeout waiting for more digits in a multi-digit input.
+loops : max times to play the file when input bindings are present.
+language : language
+type : type (fs param)
+method : method (fs param)
+gender : gender (fs param)
+
+
+
+
+
+*DATA*
+ : Execute a FreeSWITCH app.
+ATTRS:
+application : The app to run
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+data : Alternate source for app data
+*DATA* : The app data
+
+
+
+DATA
+ : Send a SMS message.
+ATTRS:
+to : The dest number
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+*DATA* : The message data
+
+
+
+
+
+*DATA*
+ : Place an outbound call or transfer.
+
+ATTRS:
+context : Dialplan context.
+dialplan : Dialplan dialplan.
+caller-id-name : Caller ID Name.
+caller-id-number : Caller ID Number.
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+*DATA* : Number to dial or originate string
+
+
+
+
+
+
+ : begin recording the call. The file will be posted when the call ends.
+
+ATTRS:
+limit : Timeout in seconds.
+name : Name to use for input values.
+action : URL action to use.
+temp-action : Change url to submit to. just for the next loop.
+
+
+
+
+
+ : Start a conference call.
+
+ATTRS:
+profile : Conference profile to use.
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+
+
+
+
+ : Hangup the call
+
+ATTRS:
+cause : Hangup cause
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+
+
+
+
+ : Exit the httapi application and continue in the dialplan.
+
+
+
+
+
+
+ : Write a log line to fs_cli, console, logs, etc.
+ATTRS:
+level : The log level to use.
+clean : If true do not print log prefix.
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+
+
+ : Just continue (no-op)
+
+ATTRS:
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+
+
+
+ : Get a Channel variable (depends on permissions)
+
+ATTRS:
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+permanent : Add as a permanent param or just once.
+
+
+
+ : Call the voicemail app without requiring "execute" permissions
+
+ATTRS:
+action : Change url to submit to.
+temp-action : Change url to submit to. just for the next loop.
+check : true to check (omit to leave)
+auth-only : authenticate only and move on
+profile : profile name to use (omit for "default")
+domain : domain to use (omit for global domain variable)
+id : id to use (omit to prompt for id)
+
+
+
+
+
+CONFIGURATION:
+
+:
+
+debug : false Print debug data
+file-cache-ttl : 300 How long to wait before checking the server to see if audio file has changed.
+file-not-found-expires : 300 How long to still preserve cached audio files that are not found by the server.
+
+ : CREATE NEW PROFILE TO REFERENCE BY NAME
+gateway-url : "" Initial URL to connect to.
+gateway-credentials : "" HTTP credentials.
+auth-scheme : basic auth scheme to use. [basic|digest|NTLM|GSS-NEGOTIATE|any]
+disable-100-continue : true Disable the 100 continue feature.
+method : "" METHOD name to send.
+timeout : 0 Timeout waiting for response.
+enable-cacert-check : false Check CA/CERT.
+ssl-cert-path : "" path to file.
+ssl-key-path : "" path to file.
+ssl-key-password : "" password to use.
+ssl-version : "" ssl version
+ssl-cacert-file : "" CA/CERT file.
+enable-ssl-verifyhost : "" Verify ssl host.
+cookie-file : "" Path to file to use for cookie.
+enable-post-var : "" Specify specifc param names ok to send.
+bind-local : "" Interface to bind to.
+default-profile : default Profile to use when not specified.
+user-agent : mod_httapi/1.0 User Agent header value.
+
+
+: * = default
+
+
+*set-params : tag can be parsed for session params.
+set-vars : tag can be parsed to set channel vars.
+extended-data : Extended data is sent like full channel event data.
+execute-apps : tag is enabled to execute apps.
+expand-vars : Allow expansion of FS ${variables}. (this opens up all FSAPI calls)
+*dial : tag is enabled allowing outbound dialing.
+dial-set-context : context attribute is permitted.
+dial-set-dialplan : dialplan attribute is permitted.
+dial-set-cid-name : cid_name attribute is permitted.
+dial-set-cid-number : cid_number attribute is permitted.
+dial-full-originate : full originate syntax is permitted instead of just a number.
+*conference : tag is enabled allowing creation of conferences.
+conference-set-profile : attribure is permitted.
+all : all permissions are set
+none : no permissions are set
+
+
diff --git a/src/mod/applications/mod_http_cache/mod_http_cache.c b/src/mod/applications/mod_http_cache/mod_http_cache.c
index b2004b5456..b93016a5e6 100644
--- a/src/mod/applications/mod_http_cache/mod_http_cache.c
+++ b/src/mod/applications/mod_http_cache/mod_http_cache.c
@@ -40,6 +40,7 @@ SWITCH_STANDARD_API(http_cache_get);
SWITCH_STANDARD_API(http_cache_put);
SWITCH_STANDARD_API(http_cache_tryget);
SWITCH_STANDARD_API(http_cache_clear);
+SWITCH_STANDARD_API(http_cache_prefetch);
#define DOWNLOAD_NEEDED "download"
@@ -148,6 +149,16 @@ struct url_cache {
int misses;
/** Number of cache errors */
int errors;
+ /** The prefetch queue */
+ switch_queue_t *prefetch_queue;
+ /** Max size of prefetch queue */
+ int prefetch_queue_size;
+ /** Size of prefetch thread pool */
+ int prefetch_thread_count;
+ /** Shutdown flag */
+ int shutdown;
+ /** Synchronizes shutdown of cache */
+ switch_thread_rwlock_t *shutdown_lock;
};
static url_cache_t gcache;
@@ -778,6 +789,35 @@ static void setup_dir(url_cache_t *cache)
}
}
+static int isUrl(const char *filename)
+{
+ return !zstr(filename) && !strncmp("http://", filename, strlen("http://"));
+}
+
+#define HTTP_PREFETCH_SYNTAX ""
+SWITCH_STANDARD_API(http_cache_prefetch)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ char *url;
+
+ if (!isUrl(cmd)) {
+ stream->write_function(stream, "USAGE: %s\n", HTTP_PREFETCH_SYNTAX);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ /* send to thread pool */
+ url = strdup(cmd);
+ if (switch_queue_trypush(gcache.prefetch_queue, url) != SWITCH_STATUS_SUCCESS) {
+ switch_safe_free(url);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to queue prefetch request\n");
+ stream->write_function(stream, "-ERR\n");
+ } else {
+ stream->write_function(stream, "+OK\n");
+ }
+
+ return status;
+}
+
#define HTTP_GET_SYNTAX ""
/**
* Get a file from the cache, download if it isn't cached
@@ -789,7 +829,7 @@ SWITCH_STANDARD_API(http_cache_get)
switch_memory_pool_t *pool = NULL;
char *filename;
- if (zstr(cmd) || strncmp("http://", cmd, strlen("http://"))) {
+ if (!isUrl(cmd)) {
stream->write_function(stream, "USAGE: %s\n", HTTP_GET_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
@@ -911,6 +951,44 @@ SWITCH_STANDARD_API(http_cache_clear)
return SWITCH_STATUS_SUCCESS;
}
+
+/**
+ * Thread to prefetch URLs
+ * @param thread the thread
+ * @param obj started flag
+ * @return NULL
+ */
+static void *SWITCH_THREAD_FUNC prefetch_thread(switch_thread_t *thread, void *obj)
+{
+ int *started = obj;
+ void *url = NULL;
+
+ switch_thread_rwlock_rdlock(gcache.shutdown_lock);
+ *started = 1;
+
+ // process prefetch requests
+ while (!gcache.shutdown) {
+ if (switch_queue_pop(gcache.prefetch_queue, &url) == SWITCH_STATUS_SUCCESS) {
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute("http_get", url, NULL, &stream);
+ switch_safe_free(stream.data);
+ switch_safe_free(url);
+ }
+ url = NULL;
+ }
+
+ // shutting down- clear the queue
+ while (switch_queue_trypop(gcache.prefetch_queue, &url) == SWITCH_STATUS_SUCCESS) {
+ switch_safe_free(url);
+ url = NULL;
+ }
+
+ switch_thread_rwlock_unlock(gcache.shutdown_lock);
+
+ return NULL;
+}
+
/**
* Configure the module
* @param cache to configure
@@ -933,6 +1011,8 @@ static switch_status_t do_config(url_cache_t *cache)
max_urls = 4000;
default_max_age_sec = 86400;
cache->location = SWITCH_PREFIX_DIR "/http_cache";
+ cache->prefetch_queue_size = 100;
+ cache->prefetch_thread_count = 8;
/* get params */
settings = switch_xml_child(cfg, "settings");
@@ -949,6 +1029,12 @@ static switch_status_t do_config(url_cache_t *cache)
} else if (!strcasecmp(var, "default-max-age")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting default-max-age to %s\n", val);
default_max_age_sec = atoi(val);
+ } else if (!strcasecmp(var, "prefetch-queue-size")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting prefetch-queue-size to %s\n", val);
+ cache->prefetch_queue_size = atoi(val);
+ } else if (!strcasecmp(var, "prefetch-thread-count")) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting prefetch-thread-count to %s\n", val);
+ cache->prefetch_thread_count = atoi(val);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var);
}
@@ -971,6 +1057,16 @@ static switch_status_t do_config(url_cache_t *cache)
status = SWITCH_STATUS_TERM;
goto done;
}
+ if (cache->prefetch_queue_size <= 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "prefetch-queue-size must be > 0\n");
+ status = SWITCH_STATUS_TERM;
+ goto done;
+ }
+ if (cache->prefetch_thread_count <= 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "prefetch-thread-count must be > 0\n");
+ status = SWITCH_STATUS_TERM;
+ goto done;
+ }
cache->max_url = max_urls;
cache->default_max_age = (default_max_age_sec * 1000 * 1000); /* convert from seconds to nanoseconds */
@@ -992,6 +1088,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
SWITCH_ADD_API(api, "http_tryget", "HTTP GET from cache only", http_cache_tryget, HTTP_GET_SYNTAX);
SWITCH_ADD_API(api, "http_put", "HTTP PUT", http_cache_put, HTTP_PUT_SYNTAX);
SWITCH_ADD_API(api, "http_clear_cache", "Clear the cache", http_cache_clear, HTTP_CACHE_CLEAR_SYNTAX);
+ SWITCH_ADD_API(api, "http_prefetch", "Prefetch document in a background thread. Use http_get to get the prefetched document", http_cache_prefetch, HTTP_PREFETCH_SYNTAX);
memset(&gcache, 0, sizeof(url_cache_t));
gcache.pool = pool;
@@ -1002,6 +1099,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
switch_core_hash_init(&gcache.map, gcache.pool);
switch_mutex_init(&gcache.mutex, SWITCH_MUTEX_UNNESTED, gcache.pool);
+ switch_thread_rwlock_create(&gcache.shutdown_lock, gcache.pool);
/* create the queue */
gcache.queue.max_size = gcache.max_url;
@@ -1011,6 +1109,21 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
setup_dir(&gcache);
+ /* Start the prefetch threads */
+ switch_queue_create(&gcache.prefetch_queue, gcache.prefetch_queue_size, gcache.pool);
+ for (int i = 0; i < gcache.prefetch_thread_count; i++) {
+ int started = 0;
+ switch_thread_t *thread;
+ switch_threadattr_t *thd_attr = NULL;
+ switch_threadattr_create(&thd_attr, gcache.pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+ switch_thread_create(&thread, thd_attr, prefetch_thread, &started, gcache.pool);
+ while (!started) {
+ switch_sleep(1000);
+ }
+ }
+
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -1020,6 +1133,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_http_cache_load)
*/
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_http_cache_shutdown)
{
+ gcache.shutdown = 1;
+ switch_queue_interrupt_all(gcache.prefetch_queue);
+ switch_thread_rwlock_wrlock(gcache.shutdown_lock);
+
url_cache_clear(&gcache, NULL);
switch_core_hash_destroy(&gcache.map);
switch_mutex_destroy(gcache.mutex);
diff --git a/src/mod/applications/mod_ladspa/mod_ladspa.c b/src/mod/applications/mod_ladspa/mod_ladspa.c
index 968f2d7879..efc75e03ee 100644
--- a/src/mod/applications/mod_ladspa/mod_ladspa.c
+++ b/src/mod/applications/mod_ladspa/mod_ladspa.c
@@ -634,6 +634,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ladspa_load)
setenv("LADSPA_PATH", "/usr/lib64/ladspa/:/usr/local/lib/ladspa", 1);
} else if (switch_directory_exists("/usr/lib/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
setenv("LADSPA_PATH", "/usr/lib/ladspa/:/usr/local/lib/ladspa", 1);
+ } else if (switch_directory_exists("/usr/local/lib/ladspa/", pool) == SWITCH_STATUS_SUCCESS) {
+ setenv("LADSPA_PATH", "/usr/local/lib/ladspa", 1);
}
}
diff --git a/src/mod/applications/mod_lcr/mod_lcr.c b/src/mod/applications/mod_lcr/mod_lcr.c
index 3c5062ed6f..d24aa2df1a 100644
--- a/src/mod/applications/mod_lcr/mod_lcr.c
+++ b/src/mod/applications/mod_lcr/mod_lcr.c
@@ -1535,7 +1535,14 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", caller_profile->destination_number, caller_profile->context);
routes.lookup_number = caller_profile->destination_number;
- routes.cid = (char *) caller_profile->caller_id_number;
+
+ if (caller_profile) {
+ routes.cid = (char *) switch_channel_get_variable(channel, "effective_caller_id_number");
+ if (!routes.cid) {
+ routes.cid = (char *) caller_profile->caller_id_number;
+ }
+ }
+
if (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) {
if ((extension = switch_caller_extension_new(session, caller_profile->destination_number, caller_profile->destination_number)) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "memory error!\n");
diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp
index 973827724d..85bbd0ee4a 100644
--- a/src/mod/applications/mod_mongo/mod_mongo.cpp
+++ b/src/mod/applications/mod_mongo/mod_mongo.cpp
@@ -1,3 +1,34 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Tamas Cseke
+ *
+ * mod_mongo.cpp -- API for MongoDB
+ *
+ */
+
#include
#include "mod_mongo.h"
diff --git a/src/mod/applications/mod_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h
index 57fdd09fdb..a1c8322bd7 100644
--- a/src/mod/applications/mod_mongo/mod_mongo.h
+++ b/src/mod/applications/mod_mongo/mod_mongo.h
@@ -1,3 +1,34 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Tamas Cseke
+ *
+ * mod_mongo.h -- API for MongoDB
+ *
+ */
+
#ifndef MOD_MONGO_H
#define MOD_MONGO_H
@@ -35,3 +66,13 @@ switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DB
#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/applications/mod_mongo/mongo_conn.cpp b/src/mod/applications/mod_mongo/mongo_conn.cpp
index dd23b00310..075b8f85d6 100644
--- a/src/mod/applications/mod_mongo/mongo_conn.cpp
+++ b/src/mod/applications/mod_mongo/mongo_conn.cpp
@@ -1,3 +1,33 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Tamas Cseke
+ *
+ * mongo_conn.cpp -- MongoDB connection pool
+ *
+ */
#include
#include "mod_mongo.h"
@@ -169,3 +199,14 @@ switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DB
return status;
}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/applications/mod_nibblebill/mod_nibblebill.c b/src/mod/applications/mod_nibblebill/mod_nibblebill.c
index 2cd772ece0..cb9942e985 100755
--- a/src/mod/applications/mod_nibblebill/mod_nibblebill.c
+++ b/src/mod/applications/mod_nibblebill/mod_nibblebill.c
@@ -397,6 +397,7 @@ static switch_status_t do_billing(switch_core_session_t *session)
switch_size_t retsize;
switch_time_exp_t tm;
const char *billrate;
+ const char *billincrement;
const char *billaccount;
float nobal_amt = globals.nobal_amt;
//float lowbal_amt = globals.lowbal_amt;
@@ -416,6 +417,7 @@ static switch_status_t do_billing(switch_core_session_t *session)
/* Variables kept in FS but relevant only to this module */
billrate = switch_channel_get_variable(channel, "nibble_rate");
+ billincrement = switch_channel_get_variable(channel, "nibble_increment");
billaccount = switch_channel_get_variable(channel, "nibble_account");
if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) {
@@ -493,8 +495,14 @@ static switch_status_t do_billing(switch_core_session_t *session)
(int) ((ts - nibble_data->lastts) / 1000000), date);
if ((ts - nibble_data->lastts) >= 0) {
- /* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
- billamount = ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
+ /* If billincrement is set we bill by it and not by time elapsed */
+ if (!(switch_strlen_zero(billincrement))) {
+ float chargedunits = ((int)((ts - nibble_data->lastts) / 1000000) <= (int)atof(billincrement)) ? ((float)atof(billincrement) * 1000000) : ceil((ts - nibble_data->lastts) / ((float)atof(billincrement) * 1000000)) * ((float)atof(billincrement) * 1000000);
+ billamount = ((float) atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments;
+ } else {
+ /* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
+ billamount = ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
+ }
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount,
uuid, nibble_data->total);
diff --git a/src/mod/applications/mod_skel/mod_skel.2010.vcxproj b/src/mod/applications/mod_skel/mod_skel.2010.vcxproj
index e1f1bf8c84..6c9d6763f5 100644
--- a/src/mod/applications/mod_skel/mod_skel.2010.vcxproj
+++ b/src/mod/applications/mod_skel/mod_skel.2010.vcxproj
@@ -63,10 +63,6 @@
<_ProjectFileVersion>10.0.30319.1
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
- $(Platform)\$(Configuration)\
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp.c b/src/mod/applications/mod_spandsp/mod_spandsp.c
index 8c64d78ddc..68ac50f137 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp.c
+++ b/src/mod/applications/mod_spandsp/mod_spandsp.c
@@ -446,7 +446,7 @@ switch_status_t load_configuration(switch_bool_t reload)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Missing name\n");
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Adding tone_descriptor: %s\n", name);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding tone_descriptor: %s\n", name);
if (tone_descriptor_create(&descriptor, name, spandsp_globals.config_pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to allocate tone_descriptor: %s\n", name);
switch_goto_status(SWITCH_STATUS_FALSE, done);
@@ -467,7 +467,7 @@ switch_status_t load_configuration(switch_bool_t reload)
"Unable to add tone_descriptor: %s, tone: %s. (too many tones)\n", name, tone_name);
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Adding tone_descriptor: %s, tone: %s(%d)\n", name, tone_name, id);
/* add elements to tone */
for (element = switch_xml_child(tone, "element"); element; element = switch_xml_next(element)) {
@@ -502,7 +502,7 @@ switch_status_t load_configuration(switch_bool_t reload)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid element param.\n");
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Adding tone_descriptor: %s, tone: %s(%d), element (%d, %d, %d, %d)\n", name, tone_name, id, freq1, freq2, min, max);
tone_descriptor_add_tone_element(descriptor, id, freq1, freq2, min, max);
}
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
index 2ba6c1af2f..f1d56a92c5 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
+++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c
@@ -1303,7 +1303,7 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat
prefix = spandsp_globals.prepend_string;
}
- if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%ld.tif", spandsp_globals.spool, prefix, spandsp_globals.total_sessions, time))) {
+ if (!(pvt->filename = switch_core_session_sprintf(session, "%s/%s-%ld-%" SWITCH_TIME_T_FMT ".tif", spandsp_globals.spool, prefix, spandsp_globals.total_sessions, time))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot automatically set fax RX destination file\n");
goto done;
}
@@ -1683,7 +1683,7 @@ static switch_status_t t38_gateway_on_consume_media(switch_core_session_t *sessi
switch_codec_implementation_t read_impl = { 0 };
int16_t *buf = NULL;
switch_status_t status;
- switch_size_t tx;
+ int tx;
const char *t38_trace = switch_channel_get_variable(channel, "t38_trace");
char *trace_read, *trace_write;
zap_socket_t read_fd = FAX_INVALID_SOCKET, write_fd = FAX_INVALID_SOCKET;
diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_modem.h b/src/mod/applications/mod_spandsp/mod_spandsp_modem.h
index dfb946f7a1..ae9d64e71b 100644
--- a/src/mod/applications/mod_spandsp/mod_spandsp_modem.h
+++ b/src/mod/applications/mod_spandsp/mod_spandsp_modem.h
@@ -49,6 +49,9 @@
#ifdef __APPLE__
#include
#include
+#elif defined(__FreeBSD__)
+#include
+#include
#else
#include
#endif
@@ -57,8 +60,6 @@
#include
#include
#ifndef WIN32
-#ifdef __UCLIBC__
-#else
#if defined(HAVE_BYTESWAP_H)
#include
#elif defined(USE_SYS_ENDIAN_H)
@@ -68,6 +69,7 @@
#define bswap_16 OSSwapInt16
#define bswap_32 OSSwapInt32
#define bswap_64 OSSwapInt64
+#elif defined (__UCLIBC__)
#else
#define bswap_16(value) \
((((value) & 0xff) << 8) | ((value) >> 8))
@@ -84,7 +86,6 @@
#include
#include
#endif
-#endif
#include
#include
#ifndef WIN32
diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c
index e51192809f..9a237ac44a 100644
--- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c
+++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c
@@ -428,6 +428,9 @@ SWITCH_STANDARD_APP(valet_parking_function)
char *dest;
int in = -1;
+ const char *timeout, *orbit_exten, *orbit_dialplan, *orbit_context;
+ char *timeout_str = "", *orbit_exten_str = "", *orbit_dialplan_str = "", *orbit_context_str = "";
+
lot = valet_find_lot(lot_name, SWITCH_TRUE);
switch_assert(lot);
@@ -586,7 +589,28 @@ SWITCH_STANDARD_APP(valet_parking_function)
music = "silence_stream://-1";
}
- dest = switch_core_session_sprintf(session, "set:valet_ticket=%s,set:valet_hold_music=%s,sleep:1000,valet_park:%s %s",
+ if ((orbit_exten = switch_channel_get_variable(channel, "valet_parking_orbit_exten"))) {
+ orbit_exten_str = switch_core_session_sprintf(session, "set:valet_parking_orbit_exten=%s,", orbit_exten);
+ }
+
+ if ((orbit_dialplan = switch_channel_get_variable(channel, "valet_parking_orbit_dialplan"))) {
+ orbit_dialplan_str = switch_core_session_sprintf(session, "set:valet_parking_orbit_dialplan=%s,", orbit_dialplan);
+ }
+
+ if ((orbit_context = switch_channel_get_variable(channel, "valet_parking_orbit_context"))) {
+ orbit_context_str = switch_core_session_sprintf(session, "set:valet_parking_orbit_context=%s,", orbit_context);
+ }
+
+ if ((timeout = switch_channel_get_variable(channel, "valet_parking_timeout"))) {
+ timeout_str = switch_core_session_sprintf(session, "set:valet_parking_timeout=%s,", timeout);
+ }
+
+ dest = switch_core_session_sprintf(session, "%s%s%s%s"
+ "set:valet_ticket=%s,set:valet_hold_music=%s,sleep:1000,valet_park:%s %s",
+ timeout_str,
+ orbit_exten_str,
+ orbit_dialplan_str,
+ orbit_context_str,
token->uuid, music, lot_name, ext);
switch_channel_set_variable(channel, "inline_destination", dest);
diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c
index efde2a3278..f456ceecc3 100644
--- a/src/mod/applications/mod_voicemail/mod_voicemail.c
+++ b/src/mod/applications/mod_voicemail/mod_voicemail.c
@@ -989,6 +989,8 @@ typedef enum {
#define VM_ENTER_ID_MACRO "voicemail_enter_id"
#define VM_ENTER_PASS_MACRO "voicemail_enter_pass"
#define VM_FAIL_AUTH_MACRO "voicemail_fail_auth"
+#define VM_CHANGE_PASS_SUCCESS_MACRO "voicemail_change_pass_success"
+#define VM_CHANGE_PASS_FAIL_MACRO "voicemail_change_pass_fail"
#define VM_ABORT_MACRO "voicemail_abort"
#define VM_HELLO_MACRO "voicemail_hello"
#define VM_GOODBYE_MACRO "voicemail_goodbye"
@@ -2164,28 +2166,52 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
char macro[256] = "";
switch_event_t *params;
switch_xml_t xx_user, xx_domain, xx_domain_root;
+ int fail = 0;
+ int ok = 0;
- switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", VM_ENTER_PASS_MACRO, profile->terminator_key);
- TRY_CODE(switch_ivr_read(session, 0, 255, macro, NULL, buf, sizeof(buf), 10000, profile->terminator_key, 0));
- sql = switch_mprintf("update voicemail_prefs set password='%s' where username='%s' and domain='%s'", buf, myid, domain_name);
- vm_execute_sql(profile, sql, profile->mutex);
- switch_safe_free(file_path);
- switch_safe_free(sql);
+ while (!ok) {
+ fail = 0;
+ switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", VM_ENTER_PASS_MACRO, profile->terminator_key);
+ TRY_CODE(switch_ivr_read(session, 0, 255, macro, NULL, buf, sizeof(buf), 10000, profile->terminator_key, 0));
+
- switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "change-password");
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User-Password", buf);
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid);
- switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
- switch_channel_event_set_data(channel, params);
-
- if (switch_xml_locate_user("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
- &xx_domain_root, &xx_domain, &xx_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
- switch_xml_free(xx_domain_root);
+ switch_event_create_subclass(¶ms, SWITCH_EVENT_CUSTOM, VM_EVENT_MAINT);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Action", "change-password");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User-Password", buf);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-User", myid);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "VM-Domain", domain_name);
+ switch_channel_event_set_data(channel, params);
+
+ if (switch_xml_locate_user("id", myid, domain_name, switch_channel_get_variable(channel, "network_addr"),
+ &xx_domain_root, &xx_domain, &xx_user, NULL, params) == SWITCH_STATUS_SUCCESS) {
+ switch_xml_t x_result;
+
+ if ((x_result = switch_xml_child(xx_user, "result"))) {
+ if (!switch_true(switch_xml_attr_soft(x_result, "success"))) {
+ fail = 1;
+ }
+ }
+
+ switch_xml_free(xx_domain_root);
+ }
+
+ if (fail) {
+ /* add feedback for user - let him/her know that the password they tried to change to is not allowed */
+ /* change the following macro to VM_CHANGE_PASS_FAIL_MACRO when new prompts have been recorded */
+ switch_ivr_phrase_macro(session, VM_FAIL_AUTH_MACRO, NULL, NULL, NULL);
+ } else {
+ sql = switch_mprintf("update voicemail_prefs set password='%s' where username='%s' and domain='%s'", buf, myid, domain_name);
+ vm_execute_sql(profile, sql, profile->mutex);
+ switch_safe_free(file_path);
+ switch_safe_free(sql);
+ ok = 1;
+ /* add feedback for user - let him/her know that password change was successful */
+ switch_ivr_phrase_macro(session, VM_CHANGE_PASS_SUCCESS_MACRO, NULL, NULL, NULL);
+ }
+
+ switch_event_destroy(¶ms);
}
- switch_event_fire(¶ms);
-
} else if (!strcmp(input, profile->record_name_key)) {
switch_event_t *params;
file_path = switch_mprintf("%s%srecorded_name.%s", dir_path, SWITCH_PATH_SEPARATOR, profile->file_ext);
@@ -2498,19 +2524,21 @@ static void voicemail_check_main(switch_core_session_t *session, vm_profile_t *p
status = switch_ivr_phrase_macro(session, VM_GOODBYE_MACRO, NULL, NULL, NULL);
}
- if (x_user) {
- switch_xml_free(x_user);
- x_user = NULL;
- }
-
if (auth_only) {
if (authed) {
switch_channel_set_variable(channel, "user_pin_authenticated", "true");
+ switch_channel_set_variable(channel, "user_pin_authenticated_user", myid);
+ if (!zstr(myid)) switch_ivr_set_user(session, myid);
} else {
switch_channel_hangup(channel, SWITCH_CAUSE_USER_CHALLENGE);
}
}
+ if (x_user) {
+ switch_xml_free(x_user);
+ x_user = NULL;
+ }
+
}
@@ -3403,7 +3431,7 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
status = create_file(session, profile, record_macro, file_path, &message_len, SWITCH_TRUE, key_buf, buf);
- if ((status == SWITCH_STATUS_NOTFOUND)) {
+ if (status == SWITCH_STATUS_NOTFOUND) {
goto end;
}
@@ -3431,7 +3459,20 @@ static switch_status_t voicemail_leave_main(switch_core_session_t *session, vm_p
switch_core_session_get_pool(session), caller_id_name, caller_id_number, NULL, SWITCH_FALSE,
session ? switch_core_session_get_uuid(session) : NULL, session);
switch_event_destroy(&vars);
- if (status != SWITCH_STATUS_SUCCESS) {
+ if (status == SWITCH_STATUS_SUCCESS) {
+ switch_core_time_duration_t duration;
+ char duration_str[80];
+ switch_time_t l_duration = switch_time_make(message_len, 0);
+
+ switch_core_measure_time(l_duration, &duration);
+ duration.day += duration.yr * 365;
+ duration.hr += duration.day * 24;
+
+ switch_snprintf(duration_str, sizeof(duration_str), "%.2u:%.2u:%.2u", duration.hr, duration.min, duration.sec);
+
+ switch_channel_set_variable(channel, "voicemail_message_len", duration_str);
+
+ } else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to deliver message\n");
TRY_CODE(switch_ivr_phrase_macro(session, VM_ACK_MACRO, "deleted", NULL, NULL));
}
@@ -4461,9 +4502,9 @@ SWITCH_STANDARD_API(voicemail_read_api_function)
if (mread) {
if (uuid) {
- sql = switch_mprintf("update voicemail_msgs set read_epoch=%ld,flags='save' where uuid='%q'", (long) switch_epoch_time_now(NULL), uuid);
+ sql = switch_mprintf("update voicemail_msgs set read_epoch=%ld where uuid='%q'", (long) switch_epoch_time_now(NULL), uuid);
} else {
- sql = switch_mprintf("update voicemail_msgs set read_epoch=%ld,flags='save' where domain='%q'", (long) switch_epoch_time_now(NULL), domain);
+ sql = switch_mprintf("update voicemail_msgs set read_epoch=%ld where domain='%q'", (long) switch_epoch_time_now(NULL), domain);
}
} else{
if (uuid) {
@@ -5586,6 +5627,158 @@ done:
return SWITCH_STATUS_SUCCESS;
}
+#define VM_FSDB_MSG_EMAIL_USAGE " "
+SWITCH_STANDARD_API(vm_fsdb_msg_email_function)
+{
+ const char *id = NULL, *domain = NULL, *profile_name = NULL, *uuid = NULL, *email = NULL;
+ vm_profile_t *profile = NULL;
+ char *argv[7] = { 0 };
+ char *mycmd = NULL;
+ msg_get_callback_t cbt = { 0 };
+ char *sql;
+ switch_memory_pool_t *pool;
+
+ switch_core_new_memory_pool(&pool);
+
+ if (!zstr(cmd)) {
+ mycmd = switch_core_strdup(pool, cmd);
+ switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ }
+
+ if (argv[0])
+ profile_name = argv[0];
+ if (argv[1])
+ domain = argv[1];
+ if (argv[2])
+ id = argv[2];
+ if (argv[3])
+ uuid = argv[3];
+ if (argv[4])
+ email = argv[4];
+
+ if (!profile_name || !domain || !id || !uuid || !email) {
+ stream->write_function(stream, "-ERR Missing Arguments\n");
+ goto done;
+ }
+
+ if (!(profile = get_profile(profile_name))) {
+ stream->write_function(stream, "-ERR Profile not found\n");
+ goto done;
+ } else {
+ char *from;
+ char *headers, *header_string;
+ char *body;
+ int priority = 3;
+ switch_size_t retsize;
+ switch_time_exp_t tm;
+ char date[80] = "";
+ int total_new_messages = 0;
+ int total_saved_messages = 0;
+ int total_new_urgent_messages = 0;
+ int total_saved_urgent_messages = 0;
+ int32_t message_len = 0;
+ char *p;
+ switch_time_t l_duration = 0;
+ switch_core_time_duration_t duration;
+ char duration_str[80];
+ char *formatted_cid_num = NULL;
+
+ sql = switch_mprintf("SELECT * FROM voicemail_msgs WHERE username = '%q' AND domain = '%q' AND uuid = '%q' ORDER BY read_flags, created_epoch", id, domain, uuid);
+ memset(&cbt, 0, sizeof(cbt));
+ switch_event_create(&cbt.my_params, SWITCH_EVENT_GENERAL);
+ vm_execute_sql_callback(profile, profile->mutex, sql, message_get_callback, &cbt);
+ switch_safe_free(sql);
+
+ if (!strcasecmp(switch_event_get_header(cbt.my_params, "VM-Message-Read-Flags"), URGENT_FLAG_STRING)) {
+ priority = 1;
+ }
+
+ message_count(profile, id, domain, switch_event_get_header(cbt.my_params, "VM-Message-Folder"), &total_new_messages, &total_saved_messages,
+ &total_new_urgent_messages, &total_saved_urgent_messages);
+
+ switch_time_exp_lt(&tm, switch_time_make(atol(switch_event_get_header(cbt.my_params, "VM-Message-Received-Epoch")), 0));
+ switch_strftime(date, &retsize, sizeof(date), profile->date_fmt, &tm);
+
+ formatted_cid_num = switch_format_number(switch_event_get_header(cbt.my_params, "VM-Message-Caller-Number"));
+
+ /* Legacy Mod_VoiceMail variable */
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "Message-Type", "forwarded-voicemail");
+ switch_event_add_header(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_total_new_messages", "%d", total_new_messages);
+ switch_event_add_header(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_total_saved_messages", "%d", total_saved_messages);
+ switch_event_add_header(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_urgent_new_messages", "%d", total_new_urgent_messages);
+ switch_event_add_header(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_urgent_saved_messages", "%d", total_saved_urgent_messages);
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_current_folder", switch_event_get_header(cbt.my_params, "VM-Message-Folder"));
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_account", id);
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_domain", domain);
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_caller_id_number", switch_event_get_header(cbt.my_params, "VM-Message-Caller-Number"));
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_formatted_caller_id_number", formatted_cid_num);
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_caller_id_name", switch_event_get_header(cbt.my_params, "VM-Message-Caller-Name"));
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_file_path", switch_event_get_header(cbt.my_params, "VM-Message-File-Path"));
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_read_flags", switch_event_get_header(cbt.my_params, "VM-Message-Read-Flags"));
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_time", date);
+ switch_event_add_header(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_priority", "%d", priority);
+
+
+ message_len = atoi(switch_event_get_header(cbt.my_params, "VM-Message-Duration"));
+ switch_safe_free(formatted_cid_num);
+
+ l_duration = switch_time_make(atol(switch_event_get_header(cbt.my_params, "VM-Message-Duration")), 0);
+ switch_core_measure_time(l_duration, &duration);
+ duration.day += duration.yr * 365;
+ duration.hr += duration.day * 24;
+
+ switch_snprintf(duration_str, sizeof(duration_str), "%.2u:%.2u:%.2u", duration.hr, duration.min, duration.sec);
+
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_message_len", duration_str);
+ switch_event_add_header_string(cbt.my_params, SWITCH_STACK_BOTTOM, "voicemail_email", email);
+
+ if (zstr(profile->email_from)) {
+ from = switch_core_sprintf(pool, "%s@%s", id, domain);
+ } else {
+ from = switch_event_expand_headers(cbt.my_params, profile->email_from);;
+ }
+
+ if (zstr(profile->email_headers)) {
+ headers = switch_core_sprintf(pool,
+ "From: FreeSWITCH mod_voicemail <%s@%s>\nSubject: Voicemail from %s %s\nX-Priority: %d",
+ id, domain, switch_event_get_header(cbt.my_params, "VM-Message-Caller-Name"),
+ switch_event_get_header(cbt.my_params, "VM-Message-Caller-Number"), priority);
+ } else {
+ headers = switch_event_expand_headers(cbt.my_params, profile->email_headers);
+ }
+
+ p = headers + (strlen(headers) - 1);
+ if (*p == '\n') {
+ if (*(p - 1) == '\r') {
+ p--;
+ }
+ *p = '\0';
+ }
+
+ header_string = switch_core_sprintf(pool, "%s\nX-Voicemail-Length: %u", headers, message_len);
+
+ if (profile->email_body) {
+ body = switch_event_expand_headers(cbt.my_params, profile->email_body);
+ } else {
+ body = switch_mprintf("%u second Voicemail from %s %s", message_len, switch_event_get_header(cbt.my_params, "VM-Message-Caller-Name"), switch_event_get_header(cbt.my_params, "VM-Message-Caller-Number"));
+ }
+
+ switch_simple_email(email, from, header_string, body, switch_event_get_header(cbt.my_params, "VM-Message-File-Path"), profile->convert_cmd, profile->convert_ext);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending message to %s\n", email);
+ switch_safe_free(body);
+
+ switch_event_fire(&cbt.my_params);
+
+
+ profile_rwunlock(profile);
+ }
+ stream->write_function(stream, "-OK\n");
+done:
+ switch_core_destroy_memory_pool(&pool);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
#define VM_FSDB_MSG_COUNT_USAGE " "
SWITCH_STANDARD_API(vm_fsdb_msg_count_function)
{
@@ -5712,6 +5905,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_load)
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_get", "vm_fsdb_msg_get", vm_fsdb_msg_get_function, VM_FSDB_MSG_GET_USAGE);
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_delete", "vm_fsdb_msg_delete", vm_fsdb_msg_delete_function, VM_FSDB_MSG_DELETE_USAGE);
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_undelete", "vm_fsdb_msg_undelete", vm_fsdb_msg_undelete_function, VM_FSDB_MSG_UNDELETE_USAGE);
+ SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_email", "vm_fsdb_msg_email", vm_fsdb_msg_email_function, VM_FSDB_MSG_EMAIL_USAGE);
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_purge", "vm_fsdb_msg_purge", vm_fsdb_msg_purge_function, VM_FSDB_MSG_PURGE_USAGE);
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_save", "vm_fsdb_msg_save", vm_fsdb_msg_save_function, VM_FSDB_MSG_SAVE_USAGE);
SWITCH_ADD_API(commands_api_interface, "vm_fsdb_msg_forward", "vm_fsdb_msg_forward", vm_fsdb_msg_forward_function, VM_FSDB_MSG_FORWARD_USAGE);
diff --git a/src/mod/applications/mod_voicemail_ivr/Makefile b/src/mod/applications/mod_voicemail_ivr/Makefile
new file mode 100644
index 0000000000..38f5aae0a7
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/Makefile
@@ -0,0 +1,3 @@
+BASE=../../../..
+LOCAL_OBJS=ivr.o utils.o config.o menu.o
+include $(BASE)/build/modmake.rules
diff --git a/src/mod/applications/mod_voicemail_ivr/config.c b/src/mod/applications/mod_voicemail_ivr/config.c
new file mode 100644
index 0000000000..d666ebe07f
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/config.c
@@ -0,0 +1,270 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * config.c -- VoiceMail IVR Config
+ *
+ */
+#include
+
+#include "config.h"
+
+const char *global_cf = "voicemail_ivr.conf";
+
+static void append_event_profile(vmivr_menu_t *menu);
+static void populate_dtmfa_from_event(vmivr_menu_t *menu);
+
+void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu) {
+ switch_xml_t cfg, xml, x_profiles, x_profile, x_keys, x_phrases, x_menus, x_menu, x_settings;
+
+ menu->profile = profile;
+
+ if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
+ goto end;
+ }
+ if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profiles group\n");
+ goto end;
+ }
+
+ if (profile->event_settings) {
+ /* TODO Replace this with a switch_event_merge_not_set(...) */
+ switch_event_t *menu_default;
+ switch_event_create(&menu_default, SWITCH_EVENT_REQUEST_PARAMS);
+ if (menu->event_settings) {
+ switch_event_merge(menu_default, menu->event_settings);
+ switch_event_destroy(&menu->event_settings);
+ }
+
+ switch_event_create(&menu->event_settings, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_event_merge(menu->event_settings, profile->event_settings);
+ switch_event_merge(menu->event_settings, menu_default);
+ switch_event_destroy(&menu_default);
+ }
+
+ {
+ const char *s_max_attempts = switch_event_get_header(menu->event_settings, "IVR-Maximum-Attempts");
+ const char *s_entry_timeout = switch_event_get_header(menu->event_settings, "IVR-Entry-Timeout");
+ menu->ivr_maximum_attempts = atoi(s_max_attempts);
+ menu->ivr_entry_timeout = atoi(s_entry_timeout);
+ }
+
+ if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile->name))) {
+ if ((x_menus = switch_xml_child(x_profile, "menus"))) {
+ if ((x_menu = switch_xml_find_child(x_menus, "menu", "name", menu->name))) {
+
+ if ((x_keys = switch_xml_child(x_menu, "keys"))) {
+ switch_event_import_xml(switch_xml_child(x_keys, "key"), "dtmf", "action", &menu->event_keys_dtmf);
+ switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "dtmf", &menu->event_keys_action);
+ switch_event_import_xml(switch_xml_child(x_keys, "key"), "action", "variable", &menu->event_keys_varname);
+ }
+ if ((x_phrases = switch_xml_child(x_menu, "phrases"))) {
+ switch_event_import_xml(switch_xml_child(x_phrases, "phrase"), "name", "value", &menu->event_phrases);
+ }
+ if ((x_settings = switch_xml_child(x_profile, "settings"))) {
+ switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &menu->event_settings);
+ }
+
+ }
+ }
+ }
+end:
+ if (xml)
+ switch_xml_free(xml);
+ return;
+
+}
+
+void menu_instance_init(vmivr_menu_t *menu) {
+ append_event_profile(menu);
+
+ populate_dtmfa_from_event(menu);
+}
+
+void menu_instance_free(vmivr_menu_t *menu) {
+ if (menu->phrase_params) {
+ switch_event_destroy(&menu->phrase_params);
+ }
+ memset(&menu->ivre_d, 0, sizeof(menu->ivre_d));
+}
+
+void menu_free(vmivr_menu_t *menu) {
+ if (menu->event_keys_dtmf) {
+ switch_event_destroy(&menu->event_keys_dtmf);
+ }
+ if (menu->event_keys_action) {
+ switch_event_destroy(&menu->event_keys_action);
+ }
+ if (menu->event_keys_varname) {
+ switch_event_destroy(&menu->event_keys_varname);
+ }
+
+ if (menu->event_phrases) {
+ switch_event_destroy(&menu->event_phrases);
+ }
+ if (menu->event_settings) {
+ switch_event_destroy(&menu->event_settings);
+ }
+
+}
+
+static void append_event_profile(vmivr_menu_t *menu) {
+
+ if (!menu->phrase_params) {
+ switch_event_create(&menu->phrase_params, SWITCH_EVENT_REQUEST_PARAMS);
+ }
+
+ /* Used for some appending function */
+ if (menu->profile && menu->profile->name && menu->profile->id && menu->profile->domain) {
+ switch_event_add_header(menu->phrase_params, SWITCH_STACK_BOTTOM, "VM-Profile", "%s", menu->profile->name);
+ switch_event_add_header(menu->phrase_params, SWITCH_STACK_BOTTOM, "VM-Account-ID", "%s", menu->profile->id);
+ switch_event_add_header(menu->phrase_params, SWITCH_STACK_BOTTOM, "VM-Account-Domain", "%s", menu->profile->domain);
+ }
+}
+
+static void populate_dtmfa_from_event(vmivr_menu_t *menu) {
+ int i = 0;
+ if (menu->event_keys_dtmf) {
+ switch_event_header_t *hp;
+
+ for (hp = menu->event_keys_dtmf->headers; hp; hp = hp->next) {
+ if (strlen(hp->name) < 3 && hp->value) { /* TODO This is a hack to discard default FS Events ! */
+ const char *varphrasename = switch_event_get_header(menu->event_keys_varname, hp->value);
+ menu->dtmfa[i++] = hp->name;
+
+ if (varphrasename && !zstr(varphrasename)) {
+ switch_event_add_header(menu->phrase_params, SWITCH_STACK_BOTTOM, varphrasename, "%s", hp->name);
+ }
+ }
+ }
+ }
+ menu->dtmfa[i++] = '\0';
+}
+
+vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name)
+{
+ vmivr_profile_t *profile = NULL;
+ switch_xml_t cfg, xml, x_profiles, x_profile, x_apis, x_settings, param;
+
+ if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
+ return profile;
+ }
+ if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
+ goto end;
+ }
+
+ if ((x_profile = switch_xml_find_child(x_profiles, "profile", "name", profile_name))) {
+ if (!(profile = switch_core_session_alloc(session, sizeof(vmivr_profile_t)))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Alloc Failure\n");
+ goto end;
+ }
+
+ profile->name = profile_name;
+
+ profile->current_msg = 0;
+ profile->current_msg_uuid = NULL;
+
+ profile->folder_name = VM_FOLDER_ROOT;
+ profile->folder_filter = VM_MSG_NOT_READ;
+
+ /* TODO Make the following configurable */
+ profile->api_profile = profile->name;
+ profile->menu_check_auth = "std_authenticate";
+ profile->menu_check_main = "std_main_menu";
+ profile->menu_check_terminate = "std_purge";
+
+ /* Populate default general settings */
+ switch_event_create(&profile->event_settings, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Maximum-Attempts", "%d", 3);
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "IVR-Entry-Timeout", "%d", 3000);
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Exit-Purge", "%s", "true");
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Password-Mask", "%s", "XXX.");
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "User-Mask", "%s", "X.");
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Format", "%s", "wav");
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Hits", "%d", 4);
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Silence-Threshold", "%d", 200);
+ switch_event_add_header(profile->event_settings, SWITCH_STACK_BOTTOM, "Record-Maximum-Length", "%d", 30);
+
+ if ((x_settings = switch_xml_child(x_profile, "settings"))) {
+ switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &profile->event_settings);
+ }
+
+ if ((x_apis = switch_xml_child(x_profile, "apis"))) {
+ int total_options = 0;
+ int total_invalid_options = 0;
+ for (param = switch_xml_child(x_apis, "api"); param; param = param->next) {
+ char *var, *val;
+ if ((var = (char *) switch_xml_attr_soft(param, "name")) && (val = (char *) switch_xml_attr_soft(param, "value"))) {
+ if (!strcasecmp(var, "msg_undelete") && !profile->api_msg_undelete)
+ profile->api_msg_undelete = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_delete") && !profile->api_msg_delete)
+ profile->api_msg_delete = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_list") && !profile->api_msg_list)
+ profile->api_msg_list = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_count") && !profile->api_msg_count)
+ profile->api_msg_count = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_save") && !profile->api_msg_save)
+ profile->api_msg_save = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_purge") && !profile->api_msg_purge)
+ profile->api_msg_purge = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_get") && !profile->api_msg_get)
+ profile->api_msg_get = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "msg_forward") && !profile->api_msg_forward)
+ profile->api_msg_forward = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "pref_greeting_set") && !profile->api_pref_greeting_set)
+ profile->api_pref_greeting_set = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "pref_recname_set") && !profile->api_pref_recname_set)
+ profile->api_pref_recname_set = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "pref_password_set") && !profile->api_pref_password_set)
+ profile->api_pref_password_set = switch_core_session_strdup(session, val);
+ else if (!strcasecmp(var, "auth_login") && !profile->api_auth_login)
+ profile->api_auth_login = switch_core_session_strdup(session, val);
+ else
+ total_invalid_options++;
+ total_options++;
+ }
+ }
+ if (total_options - total_invalid_options != 12) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing api definition for profile '%s'\n", profile_name);
+ profile = NULL;
+ }
+ }
+
+ }
+
+end:
+ switch_xml_free(xml);
+ return profile;
+}
+
+void free_profile(vmivr_profile_t *profile) {
+ if (profile->event_settings) {
+ switch_event_destroy(&profile->event_settings);
+ }
+}
diff --git a/src/mod/applications/mod_voicemail_ivr/config.h b/src/mod/applications/mod_voicemail_ivr/config.h
new file mode 100644
index 0000000000..f94fdb6f54
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/config.h
@@ -0,0 +1,107 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * config.c -- VoiceMail IVR Config
+ *
+ */
+#include "ivr.h"
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+extern const char *global_cf;
+
+#define VM_FOLDER_ROOT "inbox";
+#define VM_MSG_NOT_READ "not-read"
+#define VM_MSG_SAVED "save"
+#define VM_MSG_NEW "new"
+
+struct vmivr_profile {
+ const char *name;
+
+ const char *domain;
+ const char *id;
+
+ int current_msg;
+ const char *current_msg_uuid;
+
+ const char *folder_name;
+ const char *folder_filter;
+
+ const char *menu_check_auth;
+ const char *menu_check_main;
+ const char *menu_check_terminate;
+
+ switch_bool_t authorized;
+
+ const char *api_profile;
+ const char *api_auth_login;
+ const char *api_msg_delete;
+ const char *api_msg_undelete;
+ const char *api_msg_list;
+ const char *api_msg_count;
+ const char *api_msg_save;
+ const char *api_msg_purge;
+ const char *api_msg_get;
+ const char *api_msg_forward;
+ const char *api_pref_greeting_set;
+ const char *api_pref_recname_set;
+ const char *api_pref_password_set;
+
+ switch_event_t *event_settings;
+};
+typedef struct vmivr_profile vmivr_profile_t;
+
+struct vmivr_menu {
+ const char *name;
+ vmivr_profile_t *profile;
+
+ switch_event_t *event_keys_action;
+ switch_event_t *event_keys_dtmf;
+ switch_event_t *event_keys_varname;
+ switch_event_t *event_settings;
+ switch_event_t *event_phrases;
+
+ char *dtmfa[16];
+ switch_event_t *phrase_params;
+ ivre_data_t ivre_d;
+
+ int ivr_maximum_attempts;
+ int ivr_entry_timeout;
+};
+typedef struct vmivr_menu vmivr_menu_t;
+
+vmivr_profile_t *get_profile(switch_core_session_t *session, const char *profile_name);
+void free_profile(vmivr_profile_t *profile);
+
+void menu_init(vmivr_profile_t *profile, vmivr_menu_t *menu);
+void menu_instance_init(vmivr_menu_t *menu);
+void menu_instance_free(vmivr_menu_t *menu);
+void menu_free(vmivr_menu_t *menu);
+
+#endif /* _CONFIG_H_ */
diff --git a/src/mod/applications/mod_voicemail_ivr/ivr.c b/src/mod/applications/mod_voicemail_ivr/ivr.c
new file mode 100644
index 0000000000..4c2b2c8010
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/ivr.c
@@ -0,0 +1,255 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * ivr.c -- VoiceMail IVR Engone
+ *
+ */
+
+#include
+
+#include "ivr.h"
+
+static int match_dtmf(switch_core_session_t *session, ivre_data_t *loc) {
+ switch_bool_t is_invalid[128] = { SWITCH_FALSE };
+ int i;
+ loc->potentialMatch = NULL;
+ loc->completeMatch = NULL;
+ loc->potentialMatchCount = 0;
+
+ for (i = 0; i < loc->dtmf_received; i++) {
+ int j;
+ loc->potentialMatchCount = 0;
+ for (j = 0; !zstr(loc->dtmf_accepted[j]) && j < 128; j++) {
+ switch_bool_t cMatch = SWITCH_FALSE;
+ char test[2] = { 0 };
+
+ if (is_invalid[j])
+ continue;
+
+ test[0] = loc->dtmf_stored[i];
+ if (loc->dtmf_accepted[j][i] == 'N' && atoi(test) >= 2 && atoi(test) <= 9)
+ cMatch = SWITCH_TRUE;
+ if (loc->dtmf_accepted[j][i] == 'X' && atoi(test) >= 0 && atoi(test) <= 9) {
+ cMatch = SWITCH_TRUE;
+ }
+ if (i >= strlen(loc->dtmf_accepted[j]) - 1 && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] == '.')
+ cMatch = SWITCH_TRUE;
+ if (loc->dtmf_accepted[j][i] == loc->dtmf_stored[i])
+ cMatch = SWITCH_TRUE;
+
+ if (cMatch == SWITCH_FALSE) {
+ is_invalid[j] = SWITCH_TRUE;
+ continue;
+ }
+
+ if (i == strlen(loc->dtmf_accepted[j]) - 1 && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] == '.') {
+ loc->completeMatch = loc->dtmf_accepted[j];
+ }
+ if (i == loc->dtmf_received - 1 && loc->dtmf_received == strlen(loc->dtmf_accepted[j]) && loc->dtmf_accepted[j][strlen(loc->dtmf_accepted[j])-1] != '.') {
+ loc->completeMatch = loc->dtmf_accepted[j];
+ continue;
+ }
+ loc->potentialMatchCount++;
+ }
+ }
+
+ return 1;
+}
+
+static switch_status_t cb_on_dtmf_ignore(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+ switch (itype) {
+ case SWITCH_INPUT_TYPE_DTMF:
+ {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+ switch_channel_queue_dtmf(channel, dtmf);
+ return SWITCH_STATUS_BREAK;
+ }
+ default:
+ break;
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t cb_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+ ivre_data_t *loc = (ivre_data_t*) buf;
+
+ switch (itype) {
+ case SWITCH_INPUT_TYPE_DTMF:
+ {
+ switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+ switch_bool_t audio_was_stopped = loc->audio_stopped;
+ loc->audio_stopped = SWITCH_TRUE;
+
+ if (loc->dtmf_received >= sizeof(loc->dtmf_stored)) {
+ loc->result = RES_BUFFER_OVERFLOW;
+ break;
+ }
+ if (!loc->terminate_key || dtmf->digit != loc->terminate_key)
+ loc->dtmf_stored[loc->dtmf_received++] = dtmf->digit;
+
+ match_dtmf(session, loc);
+
+ if (loc->terminate_key && dtmf->digit == loc->terminate_key && loc->result == RES_WAITFORMORE) {
+ if (loc->potentialMatchCount == 1 && loc->completeMatch != NULL) {
+ loc->result = RES_FOUND;
+ } else {
+ loc->result = RES_INVALID;
+ }
+ return SWITCH_STATUS_BREAK;
+ } else {
+ if (loc->potentialMatchCount == 0 && loc->completeMatch != NULL) {
+ loc->result = RES_FOUND;
+ return SWITCH_STATUS_BREAK;
+ } else if (loc->potentialMatchCount > 0) {
+ loc->result = RES_WAITFORMORE;
+ if (!audio_was_stopped)
+ return SWITCH_STATUS_BREAK;
+ } else {
+ loc->result = RES_INVALID;
+ return SWITCH_STATUS_BREAK;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t ivre_init(ivre_data_t *loc, char **dtmf_accepted) {
+ int i;
+
+ memset(loc, 0, sizeof(*loc));
+
+ for (i = 0; dtmf_accepted[i] && i < 16; i++) {
+ strncpy(loc->dtmf_accepted[i], dtmf_accepted[i], 128);
+ }
+ loc->record_tone = "%(1000, 0, 640)";
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t ivre_playback_dtmf_buffered(switch_core_session_t *session, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout) {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if (switch_channel_ready(channel)) {
+ switch_input_args_t args = { 0 };
+
+ args.input_callback = cb_on_dtmf_ignore;
+
+ if (macro_name) {
+ status = switch_ivr_phrase_macro_event(session, macro_name, data, event, lang, &args);
+ }
+ } else {
+ status = SWITCH_STATUS_BREAK;
+ }
+
+ return status;
+}
+
+
+switch_status_t ivre_playback(switch_core_session_t *session, ivre_data_t *loc, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout) {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if (switch_channel_ready(channel)) {
+ switch_input_args_t args = { 0 };
+
+ args.input_callback = cb_on_dtmf;
+ args.buf = loc;
+
+ if (macro_name && loc->audio_stopped == SWITCH_FALSE && loc->result == RES_WAITFORMORE) {
+ status = switch_ivr_phrase_macro_event(session, macro_name, data, event, lang, &args);
+ }
+
+ if (switch_channel_ready(channel) && (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) && timeout && loc->result == RES_WAITFORMORE) {
+ loc->audio_stopped = SWITCH_TRUE;
+ switch_ivr_collect_digits_callback(session, &args, timeout, 0);
+ if (loc->result == RES_WAITFORMORE) {
+ if (loc->potentialMatchCount == 1 && loc->completeMatch != NULL) {
+ loc->result = RES_FOUND;
+ } else {
+ loc->result = RES_TIMEOUT;
+ }
+ }
+ }
+ } else {
+ status = SWITCH_STATUS_BREAK;
+ }
+
+ return status;
+}
+
+switch_status_t ivre_record(switch_core_session_t *session, ivre_data_t *loc, switch_event_t *event, const char *file_path, switch_file_handle_t *fh, int max_record_len, switch_size_t *record_len) {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if (switch_channel_ready(channel)) {
+ switch_input_args_t args = { 0 };
+
+ args.input_callback = cb_on_dtmf;
+ args.buf = loc;
+
+ if (loc->audio_stopped == SWITCH_FALSE && loc->result == RES_WAITFORMORE) {
+ loc->recorded_audio = SWITCH_TRUE;
+ switch_ivr_gentones(session, loc->record_tone, 0, NULL);
+ status = switch_ivr_record_file(session, fh, file_path, &args, max_record_len);
+
+ if (record_len) {
+ *record_len = fh->samples_out / (fh->samplerate ? fh->samplerate : 8000);
+ }
+
+ }
+ if (loc->result == RES_WAITFORMORE) {
+ loc->result = RES_TIMEOUT;
+ }
+
+ } else {
+ status = SWITCH_STATUS_BREAK;
+ }
+
+ return status;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/applications/mod_voicemail_ivr/ivr.h b/src/mod/applications/mod_voicemail_ivr/ivr.h
new file mode 100644
index 0000000000..a277140985
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/ivr.h
@@ -0,0 +1,66 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * ivr.h -- VoiceMail IVR Engine
+ *
+ */
+
+#ifndef _IVRE_H_
+#define _IVRE_H_
+
+struct ivre_data {
+ char dtmf_stored[128];
+ int dtmf_received;
+ char dtmf_accepted[16][128];
+ int result;
+ switch_bool_t audio_stopped;
+ switch_bool_t recorded_audio;
+ const char *potentialMatch;
+ int potentialMatchCount;
+ const char *completeMatch;
+ char terminate_key;
+ const char *record_tone;
+};
+typedef struct ivre_data ivre_data_t;
+
+#define RES_WAITFORMORE 0
+#define RES_FOUND 1
+#define RES_INVALID 3
+#define RES_TIMEOUT 4
+#define RES_BREAK 5
+#define RES_RECORD 6
+#define RES_BUFFER_OVERFLOW 99
+
+#define MAX_DTMF_SIZE_OPTION 32
+
+switch_status_t ivre_init(ivre_data_t *loc, char **dtmf_accepted);
+switch_status_t ivre_playback(switch_core_session_t *session, ivre_data_t *loc, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout);
+switch_status_t ivre_record(switch_core_session_t *session, ivre_data_t *loc, switch_event_t *event, const char *file_path, switch_file_handle_t *fh, int max_record_len, switch_size_t *record_len);
+
+switch_status_t ivre_playback_dtmf_buffered(switch_core_session_t *session, const char *macro_name, const char *data, switch_event_t *event, const char *lang, int timeout);
+#endif
diff --git a/src/mod/applications/mod_voicemail_ivr/menu.c b/src/mod/applications/mod_voicemail_ivr/menu.c
new file mode 100644
index 0000000000..73fa7f4859
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/menu.c
@@ -0,0 +1,869 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * menu.c -- VoiceMail Menu
+ *
+ */
+#include
+
+#include "ivr.h"
+#include "menu.h"
+#include "utils.h"
+#include "config.h"
+
+/* List of available menu */
+vmivr_menu_function_t menu_list[] = {
+ {"std_authenticate", vmivr_menu_authenticate},
+ {"std_main_menu", vmivr_menu_main},
+ {"std_navigator", vmivr_menu_navigator},
+ {"std_record_name", vmivr_menu_record_name},
+ {"std_set_password", vmivr_menu_set_password},
+ {"std_select_greeting_slot", vmivr_menu_select_greeting_slot},
+ {"std_record_greeting_with_slot", vmivr_menu_record_greeting_with_slot},
+ {"std_preference", vmivr_menu_preference},
+ {"std_purge", vmivr_menu_purge},
+ {"std_forward", vmivr_menu_forward},
+ { NULL, NULL }
+};
+
+void vmivr_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile) {
+ vmivr_menu_t menu = { "std_menu_purge" };
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (profile->id && profile->authorized) {
+ const char *exit_purge = switch_event_get_header(menu.event_settings, "Exit-Purge");
+ if (switch_true(exit_purge)) {
+ const char *cmd = switch_core_session_sprintf(session, "%s %s %s", profile->api_profile, profile->domain, profile->id);
+ vmivr_api_execute(session, profile->api_msg_purge, cmd);
+ }
+ }
+
+ menu_free(&menu);
+
+}
+
+void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ vmivr_menu_t menu = { "std_main_menu" };
+ int retry;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto end;
+ }
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+ char *cmd = NULL;
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+
+ cmd = switch_core_session_sprintf(session, "json %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name);
+ jsonapi2event(session, menu.phrase_params, profile->api_msg_count, cmd);
+ //initial_count_played = SWITCH_TRUE;
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0);
+
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+
+ if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored);
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (action) {
+ if (!strncasecmp(action, "new_msg:", 8)) {
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+8);
+ profile->folder_filter = VM_MSG_NEW;
+
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ } else if (!strncasecmp(action, "saved_msg:", 10)) {
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+10);
+ profile->folder_filter = VM_MSG_SAVED;
+
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ } else if (!strcasecmp(action, "return")) { /* Return to the previous menu */
+ retry = -1;
+ } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5);
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ }
+ }
+ }
+ menu_instance_free(&menu);
+
+
+ }
+
+end:
+ menu_free(&menu);
+}
+
+
+void vmivr_menu_navigator(switch_core_session_t *session, vmivr_profile_t *profile) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_event_t *msg_list_params = NULL;
+ size_t msg_count = 0;
+ size_t current_msg = 1;
+ size_t next_msg = current_msg;
+ size_t previous_msg = current_msg;
+ char *cmd = NULL;
+ int retry;
+
+ /* Different switch to control playback of phrases */
+ switch_bool_t initial_count_played = SWITCH_FALSE;
+ switch_bool_t skip_header = SWITCH_FALSE;
+ switch_bool_t skip_playback = SWITCH_FALSE;
+ switch_bool_t msg_deleted = SWITCH_FALSE;
+ switch_bool_t msg_undeleted = SWITCH_FALSE;
+ switch_bool_t msg_saved = SWITCH_FALSE;
+
+ vmivr_menu_t menu = { "std_navigator" };
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto done;
+ }
+
+ /* Get VoiceMail List And update msg count */
+ cmd = switch_core_session_sprintf(session, "json %s %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name, profile->folder_filter);
+ msg_list_params = jsonapi2event(session, NULL, profile->api_msg_list, cmd);
+ if (msg_list_params) {
+ msg_count = atol(switch_event_get_header(msg_list_params,"VM-List-Count"));
+ if (msg_count == 0) {
+ goto done;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "API message list return invalid result : %s(%s)\n", profile->api_msg_list, cmd);
+ goto done;
+ }
+
+
+ /* TODO Add Detection of new message and notify the user */
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+ switch_core_session_message_t msg = { 0 };
+ char cid_buf[1024] = "";
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ previous_msg = current_msg;
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+
+ /* Prompt related to previous Message here */
+ append_event_message(session, profile, menu.phrase_params, msg_list_params, previous_msg);
+ if (msg_deleted) {
+ msg_deleted = SWITCH_FALSE;
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "deleted", menu.phrase_params, NULL, 0);
+ }
+ if (msg_undeleted) {
+ msg_undeleted = SWITCH_FALSE;
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "undeleted", menu.phrase_params, NULL, 0);
+ }
+ if (msg_saved) {
+ msg_saved = SWITCH_FALSE;
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "saved", menu.phrase_params, NULL, 0);
+ }
+ switch_event_del_header(menu.phrase_params, "VM-Message-Flags");
+
+ /* Simple Protection to not go out of msg list scope */
+ if (next_msg == 0) {
+ next_msg = 1;
+ } else if (next_msg > msg_count) {
+ next_msg = msg_count;
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "no_more_messages"), NULL, NULL, NULL, 0);
+ }
+
+ current_msg = next_msg;
+
+ /* Prompt related the current message */
+ append_event_message(session, profile, menu.phrase_params, msg_list_params, current_msg);
+
+ /* Used for extra control in phrases */
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "VM-List-Count", "%"SWITCH_SIZE_T_FMT, msg_count);
+
+ /* Display MSG CID/Name to caller */
+ switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", switch_str_nil(switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Number")), switch_str_nil(switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Name")));
+
+ msg.from = __FILE__;
+ msg.string_arg = cid_buf;
+ msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
+ switch_core_session_receive_message(session, &msg);
+
+ /* Save in profile the current msg info for other menu processing AND restoration of our current position */
+ profile->current_msg = current_msg;
+ profile->current_msg_uuid = switch_core_session_strdup(session, switch_event_get_header(menu.phrase_params, "VM-Message-UUID"));
+
+ /* TODO check if msg is gone (purged by another session, notify user and auto jump to next message or something) */
+ if (!skip_header) {
+ if (!initial_count_played) {
+ cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id);
+ jsonapi2event(session, menu.phrase_params, profile->api_msg_count, cmd);
+ initial_count_played = SWITCH_TRUE;
+ // TODO ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0);
+ }
+ if (msg_count > 0) {
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "say_msg_number"), NULL, menu.phrase_params, NULL, 0);
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "say_date"), NULL, menu.phrase_params, NULL, 0);
+ }
+ }
+ if (msg_count > 0 && !skip_playback) {
+ /* TODO Update the Read date of a message (When msg start, or when it listen compleatly ??? To be determined */
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "play_message"), NULL, menu.phrase_params, NULL, 0);
+ }
+ skip_header = SWITCH_FALSE;
+ skip_playback = SWITCH_FALSE;
+
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+
+ if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored);
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+action:
+ if (action) {
+ if (!strcasecmp(action, "skip_intro")) { /* Skip Header / Play the recording again */
+ skip_header = SWITCH_TRUE;
+ } else if (!strcasecmp(action, "next_msg")) { /* Next Message */
+ next_msg++;
+ } else if (!strcasecmp(action, "prev_msg")) { /* Previous Message */
+ next_msg--;
+ } else if (!strcasecmp(action, "delete_msg")) { /* Delete / Undelete Message */
+ const char *msg_flags = switch_event_get_header(menu.phrase_params, "VM-Message-Flags");
+ if (!msg_flags || strncasecmp(msg_flags, "delete", 6)) {
+ const char *action_on_delete = switch_event_get_header(menu.event_settings, "Nav-Action-On-Delete");
+ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID"));
+ vmivr_api_execute(session, profile->api_msg_delete, cmd);
+
+ msg_deleted = SWITCH_TRUE;
+
+ if (action_on_delete) {
+ action = action_on_delete;
+ goto action;
+ } else {
+ skip_header = skip_playback = SWITCH_TRUE;
+ }
+ } else {
+ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID"));
+ vmivr_api_execute(session, profile->api_msg_undelete, cmd);
+
+ msg_undeleted = SWITCH_TRUE;
+ }
+ } else if (!strcasecmp(action, "save_msg")) { /* Save Message */
+ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID"));
+ vmivr_api_execute(session, profile->api_msg_save, cmd);
+
+ msg_saved = SWITCH_TRUE;
+ } else if (!strcasecmp(action, "callback")) { /* CallBack caller */
+ const char *cid_num = switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Number");
+ if (cid_num) {
+ /* TODO add detection for private number */
+ switch_core_session_execute_exten(session, cid_num, "XML", profile->domain);
+ } else {
+ /* TODO Some error msg that the msg doesn't contain a caller number */
+ }
+ } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5);
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ } else if (!strcasecmp(action, "return")) { /* Return */
+ retry = -1;
+ }
+ }
+ }
+
+ /* IF the API to get the message returned us a COPY of the file menu.ivre_dally (temp file create from a DB or from a web server), delete it */
+ if (switch_true(switch_event_get_header(menu.phrase_params, "VM-Message-Private-Local-Copy"))) {
+ const char *file_path = switch_event_get_header(menu.phrase_params, "VM-Message-File-Path");
+ if (file_path && unlink(file_path) != 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path);
+ }
+ }
+ menu_instance_free(&menu);
+ }
+done:
+ switch_event_destroy(&msg_list_params);
+
+ menu_free(&menu);
+
+ return;
+}
+
+void vmivr_menu_forward(switch_core_session_t *session, vmivr_profile_t *profile) {
+
+ vmivr_menu_t menu = { "std_forward_ask_prepend" };
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *prepend_filepath = NULL;
+ int retry;
+ switch_bool_t forward_msg = SWITCH_FALSE;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto end;
+ }
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+
+ if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored);
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (action) {
+ if (!strcasecmp(action, "return")) { /* Return to the previous menu */
+ retry = -1;
+ forward_msg = SWITCH_FALSE;
+ } else if (!strcasecmp(action, "prepend")) { /* Prepend record msg */
+ vmivr_menu_t sub_menu = { "std_record_message" };
+
+ const char *tmp_filepath = NULL;
+ const char *record_format = NULL;
+
+ switch_status_t status;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &sub_menu);
+
+ record_format = switch_event_get_header(sub_menu.event_settings, "Record-Format");
+
+ tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format);
+
+ status = vmivr_menu_record(session, profile, sub_menu, tmp_filepath);
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ //char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath);
+ //char *str_num = switch_core_session_sprintf(session, "%d", gnum);
+ //vmivr_api_execute(session, profile->api_pref_greeting_set, cmd);
+ //ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0);
+ prepend_filepath = tmp_filepath;
+ retry = -1;
+ forward_msg = SWITCH_TRUE;
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "record_failed"), NULL, NULL, NULL, 0);
+ }
+ menu_free(&sub_menu);
+
+ } else if (!strcasecmp(action, "forward")) { /* Forward without prepend msg */
+ retry = -1;
+ forward_msg = SWITCH_TRUE;
+ } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5);
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ }
+ }
+ }
+ menu_instance_free(&menu);
+
+
+ }
+
+ /* Ask Extension to Forward */
+ if (forward_msg) {
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+ const char *id = NULL;
+ vmivr_menu_t sub_menu = { "std_forward_ask_extension" };
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &sub_menu);
+ switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ id = vmivr_menu_get_input_set(session, profile, sub_menu, "X.");
+
+ if (id) {
+ const char *cmd = switch_core_session_sprintf(session, "%s %s %s %s %s %s %s%s%s", profile->api_profile, profile->domain, profile->id, profile->current_msg_uuid, profile->domain, id, prepend_filepath?" ":"", prepend_filepath?prepend_filepath:"" );
+ if (vmivr_api_execute(session, profile->api_msg_forward, cmd) == SWITCH_STATUS_SUCCESS) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(sub_menu.event_phrases, "ack"), "saved", NULL, NULL, 0);
+ retry = -1;
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(sub_menu.event_phrases, "invalid_extension"), NULL, NULL, NULL, 0);
+ }
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid_input"), NULL, NULL, NULL, 0);
+ }
+ menu_free(&sub_menu);
+ /* TODO add Confirmation of the transfered number */
+ }
+ /* TODO Ask if we want to transfer the msg to more person */
+
+ }
+
+end:
+ menu_free(&menu);
+}
+
+
+void vmivr_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile) {
+ switch_status_t status;
+ vmivr_menu_t menu = { "std_record_name" };
+
+ const char *tmp_filepath = NULL;
+ const char *record_format = NULL;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ record_format = switch_event_get_header(menu.event_settings, "Record-Format");
+
+ tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format);
+
+ status = vmivr_menu_record(session, profile, menu, tmp_filepath);
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, tmp_filepath);
+ vmivr_api_execute(session, profile->api_pref_recname_set, cmd);
+ }
+}
+
+void vmivr_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile) {
+ char *password;
+ vmivr_menu_t menu = { "std_set_password" };
+ const char *password_mask = NULL;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ password_mask = switch_event_get_header(menu.event_settings, "Password-Mask");
+
+ password = vmivr_menu_get_input_set(session, profile, menu, password_mask);
+
+ if (password) {
+ char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, password);
+ if (vmivr_api_execute(session, profile->api_pref_password_set, cmd)) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "password_set"), NULL, NULL, NULL, 0);
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "password_not_set"), NULL, NULL, NULL, 0);
+ }
+ }
+
+ menu_free(&menu);
+}
+
+void vmivr_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ vmivr_menu_t menu = { "std_authenticate" };
+ int retry;
+ const char *auth_var = NULL;
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) {
+ profile->authorized = SWITCH_TRUE;
+ }
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) {
+ const char *id = profile->id, *password = NULL;
+ char *cmd = NULL;
+ const char *password_mask = switch_event_get_header(menu.event_settings, "Password-Mask");
+ const char *user_mask = switch_event_get_header(menu.event_settings, "User-Mask");
+ if (!id) {
+ vmivr_menu_t sub_menu = { "std_authenticate_ask_user" };
+ /* Initialize Menu Configs */
+ menu_init(profile, &sub_menu);
+
+ switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ id = vmivr_menu_get_input_set(session, profile, sub_menu, user_mask);
+ menu_free(&sub_menu);
+ }
+ if (!password) {
+ vmivr_menu_t sub_menu = { "std_authenticate_ask_password" };
+ /* Initialize Menu Configs */
+ menu_init(profile, &sub_menu);
+
+ switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ password = vmivr_menu_get_input_set(session, profile, sub_menu, password_mask);
+ menu_free(&sub_menu);
+ }
+ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password);
+
+ if (vmivr_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) {
+ profile->id = id;
+ profile->authorized = SWITCH_TRUE;
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0);
+ }
+ }
+ menu_free(&menu);
+}
+
+void vmivr_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile) {
+ vmivr_menu_t menu = { "std_select_greeting_slot" };
+
+ const char *result;
+ int gnum = -1;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ result = vmivr_menu_get_input_set(session, profile, menu, "X");
+
+ if (result)
+ gnum = atoi(result);
+ if (gnum != -1) {
+ char * cmd = switch_core_session_sprintf(session, "%s %s %s %d", profile->api_profile, profile->domain, profile->id, gnum);
+ if (vmivr_api_execute(session, profile->api_pref_greeting_set, cmd) == SWITCH_STATUS_SUCCESS) {
+ char *str_num = switch_core_session_sprintf(session, "%d", gnum);
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0);
+ } else {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid_slot"), NULL, NULL, NULL, 0);
+ }
+ }
+ menu_free(&menu);
+}
+
+void vmivr_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile) {
+
+ vmivr_menu_t menu = { "std_record_greeting_with_slot" };
+
+ const char *result;
+ int gnum = -1;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ result = vmivr_menu_get_input_set(session, profile, menu, "X");
+
+ if (result)
+ gnum = atoi(result);
+
+ /* If user entered 0, we don't accept it */
+ if (gnum > 0) {
+ vmivr_menu_t sub_menu = { "std_record_greeting" };
+ char *tmp_filepath = NULL;
+ const char *record_format = NULL;
+
+ switch_status_t status;
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &sub_menu);
+
+ record_format = switch_event_get_header(menu.event_settings, "Record-Format");
+
+ tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format);
+
+ status = vmivr_menu_record(session, profile, sub_menu, tmp_filepath);
+
+ if (status == SWITCH_STATUS_SUCCESS) {
+ char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath);
+ char *str_num = switch_core_session_sprintf(session, "%d", gnum);
+ vmivr_api_execute(session, profile->api_pref_greeting_set, cmd);
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0);
+ }
+ menu_free(&sub_menu);
+
+ }
+
+ menu_free(&menu);
+
+}
+
+void vmivr_menu_preference(switch_core_session_t *session, vmivr_profile_t *profile) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ int retry;
+
+ vmivr_menu_t menu = { "std_preference" };
+
+ /* Initialize Menu Configs */
+ menu_init(profile, &menu);
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto end;
+ }
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+
+ if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored);
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (action) {
+ if (!strcasecmp(action, "return")) { /* Return to the previous menu */
+ retry = -1;
+ } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5);
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ }
+ }
+ }
+ menu_instance_free(&menu);
+ }
+
+end:
+ menu_free(&menu);
+}
+
+char *vmivr_menu_get_input_set(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_t menu, const char *input_mask) {
+ char *result = NULL;
+ int retry;
+ const char *terminate_key = NULL;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto end;
+ }
+
+ terminate_key = switch_event_get_header(menu.event_keys_action, "ivrengine:terminate_entry");
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+ int i;
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ /* Find the last entry and append this one to it */
+ for (i=0; menu.dtmfa[i] && i < 16; i++){
+ }
+ menu.dtmfa[i] = (char *) input_mask;
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+ if (terminate_key) {
+ menu.ivre_d.terminate_key = terminate_key[0];
+ }
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "instructions"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+
+ if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (!strncasecmp(menu.ivre_d.completeMatch, input_mask, 1)) {
+ result = switch_core_session_strdup(session, menu.ivre_d.dtmf_stored);
+ retry = -1;
+
+ }
+ }
+ menu_instance_free(&menu);
+ }
+end:
+ return result;
+}
+
+switch_status_t vmivr_menu_record(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_t menu, const char *file_name) {
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ int retry;
+
+ switch_bool_t record_prompt = SWITCH_TRUE;
+ switch_bool_t listen_recording = SWITCH_FALSE;
+ switch_bool_t play_instruction = SWITCH_TRUE;
+
+ if (!menu.event_keys_dtmf || !menu.event_phrases) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name);
+ goto end;
+ }
+
+ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) {
+ switch_file_handle_t fh = { 0 };
+ const char *rec_silence_hits = switch_event_get_header(menu.event_settings, "Record-Silence-Hits");
+ const char *rec_silence_threshold = switch_event_get_header(menu.event_settings, "Record-Silence-Threshold");
+ const char *rec_silence_samplerate = switch_event_get_header(menu.event_settings, "Record-Sample-Rate");
+ const char *rec_maximum_length = switch_event_get_header(menu.event_settings, "Record-Maximum-Length");
+ const char *rec_minimum_length = switch_event_get_header(menu.event_settings, "Record-Minimum-Length");
+ switch_size_t record_length = 0;
+
+ /* Prepare Recording File Handle */
+ fh.thresh = atoi(rec_silence_threshold);
+ fh.silence_hits = atoi(rec_silence_hits);
+ if (rec_silence_samplerate) {
+ fh.samplerate = atoi(rec_silence_samplerate);
+ }
+
+ menu_instance_init(&menu);
+
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);
+
+ ivre_init(&menu.ivre_d, menu.dtmfa);
+
+ if (record_prompt) {
+ if (play_instruction) {
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "instructions"), NULL, menu.phrase_params, NULL, 0);
+ }
+ play_instruction = SWITCH_TRUE;
+
+ ivre_record(session, &menu.ivre_d, menu.phrase_params, file_name, &fh, atoi(rec_maximum_length), &record_length);
+ } else {
+ if (listen_recording) {
+ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "VM-Record-File-Path", "%s", file_name);
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "play_recording"), NULL, menu.phrase_params, NULL, 0);
+ listen_recording = SWITCH_FALSE;
+
+ }
+ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout);
+ }
+
+ if (menu.ivre_d.recorded_audio) {
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (rec_minimum_length && record_length < atoi(rec_minimum_length)) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "too_short"), NULL, NULL, NULL, 0);
+ unlink(file_name);
+ } else {
+ record_prompt = SWITCH_FALSE;
+ }
+
+ } else if (menu.ivre_d.result == RES_TIMEOUT) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_INVALID) {
+ ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0);
+ } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */
+ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored);
+
+ /* Reset the try count */
+ retry = menu.ivr_maximum_attempts;
+
+ if (action) {
+ if (!strcasecmp(action, "listen")) { /* Listen */
+ listen_recording = SWITCH_TRUE;
+
+ } else if (!strcasecmp(action, "save")) {
+ retry = -1;
+ status = SWITCH_STATUS_SUCCESS;
+
+ } else if (!strcasecmp(action, "rerecord")) {
+ record_prompt = SWITCH_TRUE;
+
+ } else if (!strcasecmp(action, "skip_instruction")) { /* Skip Recording Greeting */
+ play_instruction = SWITCH_FALSE;
+
+ } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */
+ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5);
+ if (fPtr) {
+ fPtr(session, profile);
+ }
+ } else if (!strcasecmp(action, "return")) { /* Return */
+ retry = -1;
+ }
+ }
+ }
+ menu_instance_free(&menu);
+ }
+
+end:
+ return status;
+}
+
+
+void (*vmivr_get_menu_function(const char *menu_name))(switch_core_session_t *session, vmivr_profile_t *profile) {
+ int i = 0;
+
+ if (menu_name) {
+ for (i=0; menu_list[i].name ; i++) {
+ if (!strcasecmp(menu_list[i].name, menu_name)) {
+ return menu_list[i].pt2Func;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/applications/mod_voicemail_ivr/menu.h b/src/mod/applications/mod_voicemail_ivr/menu.h
new file mode 100644
index 0000000000..6a49dedcba
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/menu.h
@@ -0,0 +1,64 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * menu.h -- VoiceMail IVR Menu Include
+ *
+ */
+#ifndef _MENU_H_
+#define _MENU_H_
+
+#include "config.h"
+
+void vmivr_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_navigator(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_preference(switch_core_session_t *session, vmivr_profile_t *profile);
+void vmivr_menu_forward(switch_core_session_t *session, vmivr_profile_t *profile);
+
+switch_status_t vmivr_menu_record(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_t menu, const char *file_name);
+char *vmivr_menu_get_input_set(switch_core_session_t *session, vmivr_profile_t *profile, vmivr_menu_t menu, const char *input_mask);
+
+
+struct vmivr_menu_function {
+ const char *name;
+ void (*pt2Func)(switch_core_session_t *session, vmivr_profile_t *profile);
+
+};
+typedef struct vmivr_menu_function vmivr_menu_function_t;
+
+extern vmivr_menu_function_t menu_list[];
+
+void (*vmivr_get_menu_function(const char *menu_name))(switch_core_session_t *session, vmivr_profile_t *profile);
+
+#endif /* _MENU_H_ */
+
diff --git a/src/mod/applications/mod_voicemail_ivr/mod_voicemail_ivr.c b/src/mod/applications/mod_voicemail_ivr/mod_voicemail_ivr.c
new file mode 100644
index 0000000000..bede1d0e04
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/mod_voicemail_ivr.c
@@ -0,0 +1,140 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * mod_voicemail_ivr.c -- VoiceMail IVR System
+ *
+ */
+#include
+
+#include "config.h"
+#include "menu.h"
+
+/* Prototypes */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_voicemail_ivr_shutdown);
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_voicemail_ivr_runtime);
+SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_ivr_load);
+
+/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime)
+ * Defines a switch_loadable_module_function_table_t and a static const char[] modname
+ */
+SWITCH_MODULE_DEFINITION(mod_voicemail_ivr, mod_voicemail_ivr_load, mod_voicemail_ivr_shutdown, NULL);
+
+
+#define VMIVR_DESC "voicemail_ivr"
+#define VMIVR_USAGE " profile domain [id]"
+
+SWITCH_STANDARD_APP(voicemail_ivr_function)
+{
+ const char *id = NULL;
+ const char *domain = NULL;
+ const char *profile_name = NULL;
+ vmivr_profile_t *profile = NULL;
+ char *argv[6] = { 0 };
+ char *mydata = NULL;
+
+ if (!zstr(data)) {
+ mydata = switch_core_session_strdup(session, data);
+ switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+ }
+
+ if (argv[1])
+ profile_name = argv[1];
+
+ if (argv[2])
+ domain = argv[2];
+
+ if (!strcasecmp(argv[0], "check")) {
+ if (argv[3])
+ id = argv[3];
+
+ if (domain && profile_name) {
+ profile = get_profile(session, profile_name);
+
+ if (profile) {
+ void (*fPtrAuth)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(profile->menu_check_auth);
+ void (*fPtrMain)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(profile->menu_check_main);
+ void (*fPtrTerminate)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(profile->menu_check_terminate);
+
+ profile->domain = domain;
+ profile->id = id;
+
+ if (fPtrAuth && !profile->authorized) {
+ fPtrAuth(session, profile);
+ }
+
+ if (fPtrMain && profile->authorized) {
+ fPtrMain(session, profile);
+ }
+ if (fPtrTerminate) {
+ fPtrTerminate(session, profile);
+ }
+ free_profile(profile);
+
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile '%s' not found\n", profile_name);
+ }
+ }
+ }
+ return;
+}
+
+/* Macro expands to: switch_status_t mod_voicemail_ivr_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
+SWITCH_MODULE_LOAD_FUNCTION(mod_voicemail_ivr_load)
+{
+ switch_application_interface_t *app_interface;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ SWITCH_ADD_APP(app_interface, "voicemail_ivr", "voicemail_ivr", VMIVR_DESC, voicemail_ivr_function, VMIVR_USAGE, SAF_NONE);
+
+ /* indicate that the module should continue to be loaded */
+ return status;
+}
+
+/*
+ Called when the system shuts down
+ Macro expands to: switch_status_t mod_voicemail_ivr_shutdown() */
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_voicemail_ivr_shutdown)
+{
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */
diff --git a/src/mod/applications/mod_voicemail_ivr/utils.c b/src/mod/applications/mod_voicemail_ivr/utils.c
new file mode 100644
index 0000000000..e7b374a325
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/utils.c
@@ -0,0 +1,152 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * utils.c -- VoiceMail IVR / Different utility that might need to go into the core (after cleanup)
+ *
+ */
+#include
+
+#include "utils.h"
+
+switch_status_t vmivr_merge_media_files(const char** inputs, const char *output, int rate) {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_file_handle_t fh_output = { 0 };
+ int channels = 1;
+ int j = 0;
+
+ if (switch_core_file_open(&fh_output, output, channels, rate, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open %s\n", output);
+ goto end;
+ }
+
+ for (j = 0; inputs[j] != NULL && j < 128 && status == SWITCH_STATUS_SUCCESS; j++) {
+ switch_file_handle_t fh_input = { 0 };
+ char buf[2048];
+ switch_size_t len = sizeof(buf) / 2;
+
+ if (switch_core_file_open(&fh_input, inputs[j], channels, rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open %s\n", inputs[j]);
+ status = SWITCH_STATUS_GENERR;
+ break;
+ }
+
+ while (switch_core_file_read(&fh_input, buf, &len) == SWITCH_STATUS_SUCCESS) {
+ if (switch_core_file_write(&fh_output, buf, &len) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Write error\n");
+ status = SWITCH_STATUS_GENERR;
+ break;
+ }
+ }
+
+ if (fh_input.file_interface) {
+ switch_core_file_close(&fh_input);
+ }
+ }
+
+ if (fh_output.file_interface) {
+ switch_core_file_close(&fh_output);
+ }
+end:
+ return status;
+}
+
+switch_event_t *jsonapi2event(switch_core_session_t *session, switch_event_t *apply_event, const char *api, const char *data) {
+ switch_event_t *phrases_event = NULL;
+ switch_stream_handle_t stream = { 0 };
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute(api, data, session, &stream);
+ switch_event_create_json(&phrases_event, (char *) stream.data);
+ switch_safe_free(stream.data);
+
+ if (apply_event) {
+ switch_event_header_t *hp;
+ for (hp = phrases_event->headers; hp; hp = hp->next) {
+ if (!strncasecmp(hp->name, "VM-", 3)) {
+ switch_event_add_header(apply_event, SWITCH_STACK_BOTTOM, hp->name, "%s", hp->value);
+ }
+ }
+ switch_event_destroy(&phrases_event);
+ phrases_event = apply_event;
+
+ }
+
+ return phrases_event;
+}
+
+char *generate_random_file_name(switch_core_session_t *session, const char *mod_name, const char *file_extension) {
+ char rand_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = "";
+ switch_uuid_t srand_uuid;
+
+ switch_uuid_get(&srand_uuid);
+ switch_uuid_format(rand_uuid, &srand_uuid);
+
+ return switch_core_session_sprintf(session, "%s%s%s_%s.%s", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, mod_name, rand_uuid, file_extension);
+
+}
+
+switch_status_t vmivr_api_execute(switch_core_session_t *session, const char *apiname, const char *arguments) {
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ switch_stream_handle_t stream = { 0 };
+
+ SWITCH_STANDARD_STREAM(stream);
+ switch_api_execute(apiname, arguments, session, &stream);
+ if (!strncasecmp(stream.data, "-ERR", 4)) {
+ status = SWITCH_STATUS_GENERR;
+ }
+ switch_safe_free(stream.data);
+ return status;
+}
+
+void append_event_message(switch_core_session_t *session, vmivr_profile_t *profile, switch_event_t *phrase_params, switch_event_t *msg_list_event, size_t current_msg) {
+
+ char *varname;
+ char *apicmd;
+ char *total_msg = NULL;
+
+ if (!msg_list_event || !(total_msg = switch_event_get_header(msg_list_event, "VM-List-Count")) || current_msg > atoi(total_msg)) {
+ /* TODO Error MSG */
+ return;
+ }
+
+ varname = switch_mprintf("VM-List-Message-%" SWITCH_SIZE_T_FMT "-UUID", current_msg);
+ apicmd = switch_mprintf("json %s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(msg_list_event, varname));
+
+ switch_safe_free(varname);
+
+ jsonapi2event(session, phrase_params, profile->api_msg_get, apicmd);
+
+ /* TODO Set these 2 header correctly */
+ switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Type", "%s", "new");
+ switch_event_add_header(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Number", "%"SWITCH_SIZE_T_FMT, current_msg);
+
+ switch_event_add_header_string(phrase_params, SWITCH_STACK_BOTTOM, "VM-Message-Private-Local-Copy", "False");
+
+ switch_safe_free(apicmd);
+}
+
diff --git a/src/mod/applications/mod_voicemail_ivr/utils.h b/src/mod/applications/mod_voicemail_ivr/utils.h
new file mode 100644
index 0000000000..a20dfe806d
--- /dev/null
+++ b/src/mod/applications/mod_voicemail_ivr/utils.h
@@ -0,0 +1,43 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Marc Olivier Chouinard
+ *
+ *
+ * utils.c -- VoiceMail IVR / Different utility that might need to go into the core (after cleanup)
+ *
+ */
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+#include "config.h"
+
+void append_event_message(switch_core_session_t *session, vmivr_profile_t *profile, switch_event_t *phrase_params, switch_event_t *msg_list_event, size_t current_msg);
+char *generate_random_file_name(switch_core_session_t *session, const char *mod_name, const char *file_extension);
+switch_event_t *jsonapi2event(switch_core_session_t *session, switch_event_t *apply_event, const char *api, const char *data);
+switch_status_t vmivr_merge_media_files(const char** inputs, const char *output, int rate);
+switch_status_t vmivr_api_execute(switch_core_session_t *session, const char *apiname, const char *arguments);
+#endif /* _UTIL_H_ */
+
diff --git a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
index 0f3bc41f14..80be1d9686 100644
--- a/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
+++ b/src/mod/asr_tts/mod_tts_commandline/mod_tts_commandline.c
@@ -105,7 +105,7 @@ static switch_status_t tts_commandline_speech_open(switch_speech_handle_t *sh, c
/* Construct temporary file name with a new UUID */
switch_uuid_get(&uuid);
switch_uuid_format(uuid_str, &uuid);
- switch_snprintf(outfile, sizeof(outfile), "%s%s.tmp.wav", SWITCH_GLOBAL_dirs.temp_dir, uuid_str);
+ switch_snprintf(outfile, sizeof(outfile), "%s%s%s.tmp.wav", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, uuid_str);
info->file = switch_core_strdup(sh->memory_pool, outfile);
info->fh = (switch_file_handle_t *) switch_core_alloc(sh->memory_pool, sizeof(switch_file_handle_t));
diff --git a/src/mod/codecs/mod_isac/LICENSE b/src/mod/codecs/mod_isac/LICENSE
new file mode 100644
index 0000000000..4c41b7b251
--- /dev/null
+++ b/src/mod/codecs/mod_isac/LICENSE
@@ -0,0 +1,29 @@
+Copyright (c) 2011, The WebRTC project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of Google nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/mod/codecs/mod_isac/Makefile b/src/mod/codecs/mod_isac/Makefile
new file mode 100644
index 0000000000..d89cf0c613
--- /dev/null
+++ b/src/mod/codecs/mod_isac/Makefile
@@ -0,0 +1,71 @@
+BASE=../../../..
+
+LOCAL_SOURCES=arith_routines.c\
+arith_routines_hist.c\
+arith_routines_logist.c\
+auto_correlation.c\
+auto_corr_to_refl_coef.c\
+bandwidth_estimator.c\
+complex_bit_reverse.c\
+complex_fft.c\
+copy_set_operations.c\
+crc.c\
+cross_correlation.c\
+decode_bwe.c\
+decode.c\
+division_operations.c\
+dot_product_with_scale.c\
+downsample_fast.c\
+encode.c\
+encode_lpc_swb.c\
+energy.c\
+entropy_coding.c\
+fft.c\
+filter_ar.c\
+filter_ar_fast_q12.c\
+filterbanks.c\
+filterbank_tables.c\
+filter_functions.c\
+filter_ma_fast_q12.c\
+get_hanning_window.c\
+get_scaling_square.c\
+ilbc_specific_functions.c\
+intialize.c\
+isac.c\
+lattice.c\
+levinson_durbin.c\
+lpc_analysis.c\
+lpc_gain_swb_tables.c\
+lpc_shape_swb12_tables.c\
+lpc_shape_swb16_tables.c\
+lpc_tables.c\
+lpc_to_refl_coef.c\
+min_max_operations.c\
+min_max_operations_neon.c\
+pitch_estimator.c\
+pitch_filter.c\
+pitch_gain_tables.c\
+pitch_lag_tables.c\
+randomization_functions.c\
+refl_coef_to_lpc.c\
+resample_48khz.c\
+resample_by_2.c\
+resample_by_2_internal.c\
+resample.c\
+resample_fractional.c\
+spectrum_ar_model_tables.c\
+splitting_filter.c\
+spl_sqrt.c\
+spl_sqrt_floor.c\
+spl_version.c\
+sqrt_of_one_minus_x_squared.c\
+transform.c\
+vector_scaling_operations.c\
+webrtc_fft_t_1024_8.c\
+webrtc_fft_t_rad.c ""
+
+LOCAL_OBJS=$(shell echo $(LOCAL_SOURCES) | sed "s/.c /.o /g")
+LOCAL_CFLAGS=-w -I.
+
+include $(BASE)/build/modmake.rules
+
diff --git a/src/mod/codecs/mod_isac/PATENTS b/src/mod/codecs/mod_isac/PATENTS
new file mode 100644
index 0000000000..190607ac26
--- /dev/null
+++ b/src/mod/codecs/mod_isac/PATENTS
@@ -0,0 +1,24 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the WebRTC code package.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive,
+no-charge, irrevocable (except as stated in this section) patent
+license to make, have made, use, offer to sell, sell, import,
+transfer, and otherwise run, modify and propagate the contents of this
+implementation of the WebRTC code package, where such license applies
+only to those patent claims, both currently owned by Google and
+acquired in the future, licensable by Google that are necessarily
+infringed by this implementation of the WebRTC code package. This
+grant does not include claims that would be infringed only as a
+consequence of further modification of this implementation. If you or
+your agent or exclusive licensee institute or order or agree to the
+institution of patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that this
+implementation of the WebRTC code package or any code incorporated
+within this implementation of the WebRTC code package constitutes
+direct or contributory patent infringement, or inducement of patent
+infringement, then any patent rights granted to you under this License
+for this implementation of the WebRTC code package shall terminate as
+of the date such litigation is filed.
diff --git a/src/mod/codecs/mod_isac/arith_routines.c b/src/mod/codecs/mod_isac/arith_routines.c
new file mode 100644
index 0000000000..31c441a7af
--- /dev/null
+++ b/src/mod/codecs/mod_isac/arith_routines.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "arith_routines.h"
+#include "settings.h"
+
+
+/*
+ * terminate and return byte stream;
+ * returns the number of bytes in the stream
+ */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata) /* in-/output struct containing bitstream */
+{
+ WebRtc_UWord8 *stream_ptr;
+
+
+ /* point to the right place in the stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+
+ /* find minimum length (determined by current interval width) */
+ if ( streamdata->W_upper > 0x01FFFFFF )
+ {
+ streamdata->streamval += 0x01000000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x01000000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ }
+ else
+ {
+ streamdata->streamval += 0x00010000;
+ /* add carry to buffer */
+ if (streamdata->streamval < 0x00010000)
+ {
+ /* propagate carry */
+ while ( !(++(*--stream_ptr)) );
+ /* put pointer back to the old value */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ }
+ /* write remaining data to bitstream */
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ *stream_ptr++ = (WebRtc_UWord8) ((streamdata->streamval >> 16) & 0x00FF);
+ }
+
+ /* calculate stream length */
+ return (int)(stream_ptr - streamdata->stream);
+}
diff --git a/src/mod/codecs/mod_isac/arith_routines.h b/src/mod/codecs/mod_isac/arith_routines.h
new file mode 100644
index 0000000000..8e5f496f98
--- /dev/null
+++ b/src/mod/codecs/mod_isac/arith_routines.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * Functions for arithmetic coding.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_
+
+#include "structs.h"
+
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ WebRtc_Word16 *dataQ7, /* input: data vector */
+ const WebRtc_UWord16 *env, /* input: side info vector defining the width of the pdf */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+/* returns the number of bytes in the stream */
+int WebRtcIsac_EncTerminate(Bitstr *streamdata); /* in-/output struct containing bitstream */
+
+/* returns the number of bytes in the stream so far */
+int WebRtcIsac_DecLogisticMulti2(
+ WebRtc_Word16 *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 *env, /* input: side info vector defining the width of the pdf */
+ const WebRtc_Word16 *dither, /* input: dither vector */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz); /* if the codec is working in 12kHz bandwidth */
+
+void WebRtcIsac_EncHistMulti(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const int *data, /* input: data vector */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistBisectMulti(
+ int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ const int N); /* input: data vector length */
+
+int WebRtcIsac_DecHistOneStepMulti(
+ int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *init_index,/* input: vector of initial cdf table search entries */
+ const int N); /* input: data vector length */
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ARITH_ROUTINES_H_ */
diff --git a/src/mod/codecs/mod_isac/arith_routines_hist.c b/src/mod/codecs/mod_isac/arith_routines_hist.c
new file mode 100644
index 0000000000..f4a13d6078
--- /dev/null
+++ b/src/mod/codecs/mod_isac/arith_routines_hist.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "settings.h"
+#include "arith_routines.h"
+
+
+/*
+ * code symbols into arithmetic bytestream
+ */
+void WebRtcIsac_EncHistMulti(Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const int *data, /* input: data vector */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord8 *stream_ptr_carry;
+ WebRtc_UWord32 cdf_lo, cdf_hi;
+ int k;
+
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ for (k=N; k>0; k--)
+ {
+ /* fetch cdf_lower and cdf_upper from cdf tables */
+ cdf_lo = (WebRtc_UWord32) *(*cdf + *data);
+ cdf_hi = (WebRtc_UWord32) *(*cdf++ + *data++ + 1);
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, using method of bisection
+ * cdf tables should be of size 2^k-1 (which corresponds to an alphabet size of 2^k-2)
+ */
+int WebRtcIsac_DecHistBisectMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *cdf_size, /* input: array of cdf table sizes+1 (power of two: 2^k) */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ const WebRtc_UWord16 *cdf_ptr;
+ int size_tmp;
+ int k;
+
+ W_lower = 0; //to remove warning -DH
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start halfway the cdf range */
+ size_tmp = *cdf_size++ >> 1;
+ cdf_ptr = *cdf + (size_tmp - 1);
+
+ /* method of bisection */
+ for ( ;; )
+ {
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ size_tmp >>= 1;
+ if (size_tmp == 0) break;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ cdf_ptr += size_tmp;
+ } else {
+ W_upper = W_tmp;
+ cdf_ptr -= size_tmp;
+ }
+ }
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ } else {
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
+
+
+
+/*
+ * function to decode more symbols from the arithmetic bytestream, taking single step up or
+ * down at a time
+ * cdf tables can be of arbitrary size, but large tables may take a lot of iterations
+ */
+int WebRtcIsac_DecHistOneStepMulti(int *data, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 **cdf, /* input: array of cdf arrays */
+ const WebRtc_UWord16 *init_index, /* input: vector of initial cdf table search entries */
+ const int N) /* input: data vector length */
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ const WebRtc_UWord16 *cdf_ptr;
+ int k;
+
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (W_upper == 0)
+ /* Should not be possible in normal operation */
+ return -2;
+
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k=N; k>0; k--)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* start at the specified table entry */
+ cdf_ptr = *cdf + (*init_index++);
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp)
+ {
+ for ( ;; )
+ {
+ W_lower = W_tmp;
+ if (cdf_ptr[0]==65535)
+ /* range check */
+ return -3;
+ W_tmp = W_upper_MSB * *++cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval <= W_tmp) break;
+ }
+ W_upper = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++ - 1);
+ } else {
+ for ( ;; )
+ {
+ W_upper = W_tmp;
+ --cdf_ptr;
+ if (cdf_ptr<*cdf) {
+ /* range check */
+ return -3;
+ }
+ W_tmp = W_upper_MSB * *cdf_ptr;
+ W_tmp += (W_upper_LSB * *cdf_ptr) >> 16;
+ if (streamval > W_tmp) break;
+ }
+ W_lower = W_tmp;
+ *data++ = (int)(cdf_ptr - *cdf++);
+ }
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/src/mod/codecs/mod_isac/arith_routines_logist.c b/src/mod/codecs/mod_isac/arith_routines_logist.c
new file mode 100644
index 0000000000..422855a4ce
--- /dev/null
+++ b/src/mod/codecs/mod_isac/arith_routines_logist.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * arith_routines.h
+ *
+ * This file contains functions for arithmatically encoding and
+ * decoding DFT coefficients.
+ *
+ */
+
+
+#include "arith_routines.h"
+
+
+
+static const WebRtc_Word32 kHistEdgesQ15[51] = {
+ -327680, -314573, -301466, -288359, -275252, -262144, -249037, -235930, -222823, -209716,
+ -196608, -183501, -170394, -157287, -144180, -131072, -117965, -104858, -91751, -78644,
+ -65536, -52429, -39322, -26215, -13108, 0, 13107, 26214, 39321, 52428,
+ 65536, 78643, 91750, 104857, 117964, 131072, 144179, 157286, 170393, 183500,
+ 196608, 209715, 222822, 235929, 249036, 262144, 275251, 288358, 301465, 314572,
+ 327680};
+
+
+static const int kCdfSlopeQ0[51] = { /* Q0 */
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 13, 23, 47, 87, 154, 315, 700, 1088,
+ 2471, 6064, 14221, 21463, 36634, 36924, 19750, 13270, 5806, 2312,
+ 1095, 660, 316, 145, 86, 41, 32, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 0};
+
+
+static const int kCdfQ16[51] = { /* Q16 */
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
+ 20, 22, 24, 29, 38, 57, 92, 153, 279, 559,
+ 994, 1983, 4408, 10097, 18682, 33336, 48105, 56005, 61313, 63636,
+ 64560, 64998, 65262, 65389, 65447, 65481, 65497, 65510, 65512, 65514,
+ 65516, 65518, 65520, 65522, 65524, 65526, 65528, 65530, 65532, 65534,
+ 65535};
+
+
+
+/* function to be converted to fixed point */
+static __inline WebRtc_UWord32 piecewise(WebRtc_Word32 xinQ15) {
+
+ WebRtc_Word32 ind, qtmp1, qtmp2, qtmp3;
+ WebRtc_UWord32 tmpUW32;
+
+
+ qtmp2 = xinQ15;
+
+ if (qtmp2 < kHistEdgesQ15[0]) {
+ qtmp2 = kHistEdgesQ15[0];
+ }
+ if (qtmp2 > kHistEdgesQ15[50]) {
+ qtmp2 = kHistEdgesQ15[50];
+ }
+
+ qtmp1 = qtmp2 - kHistEdgesQ15[0]; /* Q15 - Q15 = Q15 */
+ ind = (qtmp1 * 5) >> 16; /* 2^16 / 5 = 0.4 in Q15 */
+ /* Q15 -> Q0 */
+ qtmp1 = qtmp2 - kHistEdgesQ15[ind]; /* Q15 - Q15 = Q15 */
+ qtmp2 = kCdfSlopeQ0[ind] * qtmp1; /* Q0 * Q15 = Q15 */
+ qtmp3 = qtmp2>>15; /* Q15 -> Q0 */
+
+ tmpUW32 = kCdfQ16[ind] + qtmp3; /* Q0 + Q0 = Q0 */
+ return tmpUW32;
+}
+
+
+
+int WebRtcIsac_EncLogisticMulti2(
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ WebRtc_Word16 *dataQ7, /* input: data vector */
+ const WebRtc_UWord16 *envQ8, /* input: side info vector defining the width of the pdf */
+ const int N, /* input: data vector length / 2 */
+ const WebRtc_Word16 isSWB12kHz)
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord8 *maxStreamPtr;
+ WebRtc_UWord8 *stream_ptr_carry;
+ WebRtc_UWord32 cdf_lo, cdf_hi;
+ int k;
+
+ /* point to beginning of stream buffer */
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+
+ maxStreamPtr = streamdata->stream + STREAM_SIZE_MAX_60 - 1;
+ for (k = 0; k < N; k++)
+ {
+ /* compute cdf_lower and cdf_upper by evaluating the piecewise linear cdf */
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+
+ /* test and clip if probability gets too small */
+ while (cdf_lo+1 >= cdf_hi) {
+ /* clip */
+ if (*dataQ7 > 0) {
+ *dataQ7 -= 128;
+ cdf_hi = cdf_lo;
+ cdf_lo = piecewise((*dataQ7 - 64) * *envQ8);
+ } else {
+ *dataQ7 += 128;
+ cdf_lo = cdf_hi;
+ cdf_hi = piecewise((*dataQ7 + 64) * *envQ8);
+ }
+ }
+
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+
+ /* update interval */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+ W_lower = W_upper_MSB * cdf_lo;
+ W_lower += (W_upper_LSB * cdf_lo) >> 16;
+ W_upper = W_upper_MSB * cdf_hi;
+ W_upper += (W_upper_LSB * cdf_hi) >> 16;
+
+ /* shift interval such that it begins at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamdata->streamval += W_lower;
+
+ /* handle carry */
+ if (streamdata->streamval < W_lower)
+ {
+ /* propagate carry */
+ stream_ptr_carry = stream_ptr;
+ while (!(++(*--stream_ptr_carry)));
+ }
+
+ /* renormalize interval, store most significant byte of streamval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ W_upper <<= 8;
+ *stream_ptr++ = (WebRtc_UWord8) (streamdata->streamval >> 24);
+
+ if(stream_ptr > maxStreamPtr)
+ {
+ return -ISAC_DISALLOWED_BITSTREAM_LENGTH;
+ }
+ streamdata->streamval <<= 8;
+ }
+ }
+
+ /* calculate new stream_index */
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+
+ return 0;
+}
+
+
+
+int WebRtcIsac_DecLogisticMulti2(
+ WebRtc_Word16 *dataQ7, /* output: data vector */
+ Bitstr *streamdata, /* in-/output struct containing bitstream */
+ const WebRtc_UWord16 *envQ8, /* input: side info vector defining the width of the pdf */
+ const WebRtc_Word16 *ditherQ7,/* input: dither vector */
+ const int N, /* input: data vector length */
+ const WebRtc_Word16 isSWB12kHz)
+{
+ WebRtc_UWord32 W_lower, W_upper;
+ WebRtc_UWord32 W_tmp;
+ WebRtc_UWord32 W_upper_LSB, W_upper_MSB;
+ WebRtc_UWord32 streamval;
+ const WebRtc_UWord8 *stream_ptr;
+ WebRtc_UWord32 cdf_tmp;
+ WebRtc_Word16 candQ7;
+ int k;
+
+ stream_ptr = streamdata->stream + streamdata->stream_index;
+ W_upper = streamdata->W_upper;
+ if (streamdata->stream_index == 0) /* first time decoder is called for this stream */
+ {
+ /* read first word from bytestream */
+ streamval = *stream_ptr << 24;
+ streamval |= *++stream_ptr << 16;
+ streamval |= *++stream_ptr << 8;
+ streamval |= *++stream_ptr;
+ } else {
+ streamval = streamdata->streamval;
+ }
+
+
+ for (k = 0; k < N; k++)
+ {
+ /* find the integer *data for which streamval lies in [W_lower+1, W_upper] */
+ W_upper_LSB = W_upper & 0x0000FFFF;
+ W_upper_MSB = W_upper >> 16;
+
+ /* find first candidate by inverting the logistic cdf */
+ candQ7 = - *ditherQ7 + 64;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ if (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while (streamval > W_tmp)
+ {
+ W_lower = W_tmp;
+ candQ7 += 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_lower == W_tmp) return -1;
+ }
+ W_upper = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 - 64;
+ }
+ else
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+ while ( !(streamval > W_tmp) )
+ {
+ W_upper = W_tmp;
+ candQ7 -= 128;
+ cdf_tmp = piecewise(candQ7 * *envQ8);
+
+ W_tmp = W_upper_MSB * cdf_tmp;
+ W_tmp += (W_upper_LSB * cdf_tmp) >> 16;
+
+ /* error check */
+ if (W_upper == W_tmp) return -1;
+ }
+ W_lower = W_tmp;
+
+ /* another sample decoded */
+ *dataQ7 = candQ7 + 64;
+ }
+ ditherQ7++;
+ dataQ7++;
+ // increment only once per 4 iterations for SWB-16kHz or WB
+ // increment only once per 2 iterations for SWB-12kHz
+ envQ8 += (isSWB12kHz)? (k & 1):((k & 1) & (k >> 1));
+
+ /* shift interval to start at zero */
+ W_upper -= ++W_lower;
+
+ /* add integer to bitstream */
+ streamval -= W_lower;
+
+ /* renormalize interval and update streamval */
+ while ( !(W_upper & 0xFF000000) ) /* W_upper < 2^24 */
+ {
+ /* read next byte from stream */
+ streamval = (streamval << 8) | *++stream_ptr;
+ W_upper <<= 8;
+ }
+ }
+
+ streamdata->stream_index = (int)(stream_ptr - streamdata->stream);
+ streamdata->W_upper = W_upper;
+ streamdata->streamval = streamval;
+
+ /* find number of bytes in original stream (determined by current interval width) */
+ if ( W_upper > 0x01FFFFFF )
+ return streamdata->stream_index - 2;
+ else
+ return streamdata->stream_index - 1;
+}
diff --git a/src/mod/codecs/mod_isac/auto_corr_to_refl_coef.c b/src/mod/codecs/mod_isac/auto_corr_to_refl_coef.c
new file mode 100644
index 0000000000..b7e885898a
--- /dev/null
+++ b/src/mod/codecs/mod_isac/auto_corr_to_refl_coef.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_AutoCorrToReflCoef().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32 *R, int use_order, WebRtc_Word16 *K)
+{
+ int i, n;
+ WebRtc_Word16 tmp;
+ G_CONST WebRtc_Word32 *rptr;
+ WebRtc_Word32 L_num, L_den;
+ WebRtc_Word16 *acfptr, *pptr, *wptr, *p1ptr, *w1ptr, ACF[WEBRTC_SPL_MAX_LPC_ORDER],
+ P[WEBRTC_SPL_MAX_LPC_ORDER], W[WEBRTC_SPL_MAX_LPC_ORDER];
+
+ // Initialize loop and pointers.
+ acfptr = ACF;
+ rptr = R;
+ pptr = P;
+ p1ptr = &P[1];
+ w1ptr = &W[1];
+ wptr = w1ptr;
+
+ // First loop; n=0. Determine shifting.
+ tmp = WebRtcSpl_NormW32(*R);
+ *acfptr = (WebRtc_Word16)((*rptr++ << tmp) >> 16);
+ *pptr++ = *acfptr++;
+
+ // Initialize ACF, P and W.
+ for (i = 1; i <= use_order; i++)
+ {
+ *acfptr = (WebRtc_Word16)((*rptr++ << tmp) >> 16);
+ *wptr++ = *acfptr;
+ *pptr++ = *acfptr++;
+ }
+
+ // Compute reflection coefficients.
+ for (n = 1; n <= use_order; n++, K++)
+ {
+ tmp = WEBRTC_SPL_ABS_W16(*p1ptr);
+ if (*P < tmp)
+ {
+ for (i = n; i <= use_order; i++)
+ *K++ = 0;
+
+ return;
+ }
+
+ // Division: WebRtcSpl_div(tmp, *P)
+ *K = 0;
+ if (tmp != 0)
+ {
+ L_num = tmp;
+ L_den = *P;
+ i = 15;
+ while (i--)
+ {
+ (*K) <<= 1;
+ L_num <<= 1;
+ if (L_num >= L_den)
+ {
+ L_num -= L_den;
+ (*K)++;
+ }
+ }
+ if (*p1ptr > 0)
+ *K = -*K;
+ }
+
+ // Last iteration; don't do Schur recursion.
+ if (n == use_order)
+ return;
+
+ // Schur recursion.
+ pptr = P;
+ wptr = w1ptr;
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*p1ptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *pptr = WEBRTC_SPL_ADD_SAT_W16( *pptr, tmp );
+ pptr++;
+ for (i = 1; i <= use_order - n; i++)
+ {
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*wptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *pptr = WEBRTC_SPL_ADD_SAT_W16( *(pptr+1), tmp );
+ pptr++;
+ tmp = (WebRtc_Word16)(((WebRtc_Word32)*pptr * (WebRtc_Word32)*K + 16384) >> 15);
+ *wptr = WEBRTC_SPL_ADD_SAT_W16( *wptr, tmp );
+ wptr++;
+ }
+ }
+}
diff --git a/src/mod/codecs/mod_isac/auto_correlation.c b/src/mod/codecs/mod_isac/auto_correlation.c
new file mode 100644
index 0000000000..a00fde4bc3
--- /dev/null
+++ b/src/mod/codecs/mod_isac/auto_correlation.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_AutoCorrelation().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* in_vector,
+ int in_vector_length,
+ int order,
+ WebRtc_Word32* result,
+ int* scale)
+{
+ WebRtc_Word32 sum;
+ int i, j;
+ WebRtc_Word16 smax; // Sample max
+ G_CONST WebRtc_Word16* xptr1;
+ G_CONST WebRtc_Word16* xptr2;
+ WebRtc_Word32* resultptr;
+ int scaling = 0;
+
+#ifdef _ARM_OPT_
+#pragma message("NOTE: _ARM_OPT_ optimizations are used")
+ WebRtc_Word16 loops4;
+#endif
+
+ if (order < 0)
+ order = in_vector_length;
+
+ // Find the max. sample
+ smax = WebRtcSpl_MaxAbsValueW16(in_vector, in_vector_length);
+
+ // In order to avoid overflow when computing the sum we should scale the samples so that
+ // (in_vector_length * smax * smax) will not overflow.
+
+ if (smax == 0)
+ {
+ scaling = 0;
+ } else
+ {
+ int nbits = WebRtcSpl_GetSizeInBits(in_vector_length); // # of bits in the sum loop
+ int t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax)); // # of bits to normalize smax
+
+ if (t > nbits)
+ {
+ scaling = 0;
+ } else
+ {
+ scaling = nbits - t;
+ }
+
+ }
+
+ resultptr = result;
+
+ // Perform the actual correlation calculation
+ for (i = 0; i < order + 1; i++)
+ {
+ int loops = (in_vector_length - i);
+ sum = 0;
+ xptr1 = in_vector;
+ xptr2 = &in_vector[i];
+#ifndef _ARM_OPT_
+ for (j = loops; j > 0; j--)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1++, *xptr2++, scaling);
+ }
+#else
+ loops4 = (loops >> 2) << 2;
+
+ if (scaling == 0)
+ {
+ for (j = 0; j < loops4; j = j + 4)
+ {
+ sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
+ xptr1++;
+ xptr2++;
+ }
+
+ for (j = loops4; j < loops; j++)
+ {
+ sum += WEBRTC_SPL_MUL_16_16(*xptr1, *xptr2);
+ xptr1++;
+ xptr2++;
+ }
+ }
+ else
+ {
+ for (j = 0; j < loops4; j = j + 4)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
+ xptr1++;
+ xptr2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
+ xptr1++;
+ xptr2++;
+ }
+
+ for (j = loops4; j < loops; j++)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*xptr1, *xptr2, scaling);
+ xptr1++;
+ xptr2++;
+ }
+ }
+
+#endif
+ *resultptr++ = sum;
+ }
+
+ *scale = scaling;
+
+ return order + 1;
+}
diff --git a/src/mod/codecs/mod_isac/bandwidth_estimator.c b/src/mod/codecs/mod_isac/bandwidth_estimator.c
new file mode 100644
index 0000000000..85912efbc8
--- /dev/null
+++ b/src/mod/codecs/mod_isac/bandwidth_estimator.c
@@ -0,0 +1,1024 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * BwEstimator.c
+ *
+ * This file contains the code for the Bandwidth Estimator designed
+ * for iSAC.
+ *
+ */
+
+#include "bandwidth_estimator.h"
+#include "settings.h"
+#include "isac.h"
+
+#include
+
+/* array of quantization levels for bottle neck info; Matlab code: */
+/* sprintf('%4.1ff, ', logspace(log10(5000), log10(40000), 12)) */
+static const float kQRateTableWb[12] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23301.4f, 25900.3f, 28789.0f, 32000.0f};
+
+
+static const float kQRateTableSwb[24] =
+{
+ 10000.0f, 11115.3f, 12355.1f, 13733.1f, 15264.8f, 16967.3f,
+ 18859.8f, 20963.3f, 23153.1f, 25342.9f, 27532.7f, 29722.5f,
+ 31912.3f, 34102.1f, 36291.9f, 38481.7f, 40671.4f, 42861.2f,
+ 45051.0f, 47240.8f, 49430.6f, 51620.4f, 53810.2f, 56000.0f,
+};
+
+
+
+
+WebRtc_Word32 WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ switch(encoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->send_bw_avg = INIT_BN_EST_SWB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ switch(decoderSampRate)
+ {
+ case kIsacWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_WB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ bwest_str->rec_bw = (WebRtc_Word32)INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_WB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_WB + INIT_HDR_RATE_WB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_WB;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ bwest_str->prev_frame_length = INIT_FRAME_LEN_SWB;
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_SWB + INIT_HDR_RATE_SWB);
+ bwest_str->rec_bw = (WebRtc_Word32)INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg_Q = INIT_BN_EST_SWB;
+ bwest_str->rec_bw_avg = INIT_BN_EST_SWB + INIT_HDR_RATE_SWB;
+ bwest_str->rec_header_rate = INIT_HDR_RATE_SWB;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ bwest_str->prev_rec_rtp_number = 0;
+ bwest_str->prev_rec_arr_ts = 0;
+ bwest_str->prev_rec_send_ts = 0;
+ bwest_str->prev_rec_rtp_rate = 1.0f;
+ bwest_str->last_update_ts = 0;
+ bwest_str->last_reduction_ts = 0;
+ bwest_str->count_tot_updates_rec = -9;
+ bwest_str->rec_jitter = 10.0f;
+ bwest_str->rec_jitter_short_term = 0.0f;
+ bwest_str->rec_jitter_short_term_abs = 5.0f;
+ bwest_str->rec_max_delay = 10.0f;
+ bwest_str->rec_max_delay_avg_Q = 10.0f;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->send_max_delay_avg = 10.0f;
+
+ bwest_str->hsn_detect_rec = 0;
+
+ bwest_str->num_consec_rec_pkts_over_30k = 0;
+
+ bwest_str->hsn_detect_snd = 0;
+
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+
+ bwest_str->in_wait_period = 0;
+
+ bwest_str->change_to_WB = 0;
+
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->inWaitLatePkts = 0;
+ bwest_str->senderTimestamp = 0;
+ bwest_str->receiverTimestamp = 0;
+ return 0;
+}
+
+/* This function updates both bottle neck rates */
+/* Parameters: */
+/* rtp_number - value from RTP packet, from NetEq */
+/* frame length - length of signal frame in ms, from iSAC decoder */
+/* send_ts - value in RTP header giving send time in samples */
+/* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
+/* pksize - size of packet in bytes, from NetEq */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+WebRtc_Word16 WebRtcIsac_UpdateBandwidthEstimator(
+ BwEstimatorstr *bwest_str,
+ const WebRtc_UWord16 rtp_number,
+ const WebRtc_Word32 frame_length,
+ const WebRtc_UWord32 send_ts,
+ const WebRtc_UWord32 arr_ts,
+ const WebRtc_Word32 pksize
+ /*, const WebRtc_UWord16 Index*/)
+{
+ float weight = 0.0f;
+ float curr_bw_inv = 0.0f;
+ float rec_rtp_rate;
+ float t_diff_proj;
+ float arr_ts_diff;
+ float send_ts_diff;
+ float arr_time_noise;
+ float arr_time_noise_abs;
+
+ float delay_correction_factor = 1;
+ float late_diff = 0.0f;
+ int immediate_set = 0;
+ int num_pkts_expected;
+
+
+ // We have to adjust the header-rate if the first packet has a
+ // frame-size different than the initialized value.
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+ }
+
+ /* UPDATE ESTIMATES ON THIS SIDE */
+ /* compute far-side transmission rate */
+ rec_rtp_rate = ((float)pksize * 8.0f * 1000.0f / (float)frame_length) +
+ bwest_str->rec_header_rate;
+ // rec_rtp_rate packet bits/s + header bits/s
+
+ /* check for timer wrap-around */
+ if (arr_ts < bwest_str->prev_rec_arr_ts)
+ {
+ bwest_str->prev_rec_arr_ts = arr_ts;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ return 0;
+ }
+
+ bwest_str->num_pkts_rec++;
+
+ /* check that it's not one of the first 9 packets */
+ if ( bwest_str->count_tot_updates_rec > 0 )
+ {
+ if(bwest_str->in_wait_period > 0 )
+ {
+ bwest_str->in_wait_period--;
+ }
+
+ bwest_str->inWaitLatePkts -= ((bwest_str->inWaitLatePkts > 0)? 1:0);
+ send_ts_diff = (float)(send_ts - bwest_str->prev_rec_send_ts);
+
+ if (send_ts_diff <= (16 * frame_length)*2)
+ //doesn't allow for a dropped packet, not sure necessary to be
+ // that strict -DH
+ {
+ /* if not been updated for a long time, reduce the BN estimate */
+ if((WebRtc_UWord32)(arr_ts - bwest_str->last_update_ts) *
+ 1000.0f / FS > 3000)
+ {
+ //how many frames should have been received since the last
+ // update if too many have been dropped or there have been
+ // big delays won't allow this reduction may no longer need
+ // the send_ts_diff here
+ num_pkts_expected = (int)(((float)(arr_ts -
+ bwest_str->last_update_ts) * 1000.0f /(float) FS) /
+ (float)frame_length);
+
+ if(((float)bwest_str->num_pkts_rec/(float)num_pkts_expected) >
+ 0.9)
+ {
+ float inv_bitrate = (float) pow( 0.99995,
+ (double)((WebRtc_UWord32)(arr_ts -
+ bwest_str->last_reduction_ts)*1000.0f/FS) );
+
+ if ( inv_bitrate )
+ {
+ bwest_str->rec_bw_inv /= inv_bitrate;
+
+ //precautionary, likely never necessary
+ if (bwest_str->hsn_detect_snd &&
+ bwest_str->hsn_detect_rec)
+ {
+ if (bwest_str->rec_bw_inv > 0.000066f)
+ {
+ bwest_str->rec_bw_inv = 0.000066f;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->rec_bw_inv = 1.0f /
+ (INIT_BN_EST_WB + INIT_HDR_RATE_WB);
+ }
+ /* reset time-since-update counter */
+ bwest_str->last_reduction_ts = arr_ts;
+ }
+ else
+ //reset here?
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+ }
+ }
+ else
+ {
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->num_pkts_rec = 0;
+ }
+
+
+ /* temporarily speed up adaptation if frame length has changed */
+ if ( frame_length != bwest_str->prev_frame_length )
+ {
+ bwest_str->count_tot_updates_rec = 10;
+ bwest_str->rec_header_rate = (float)HEADER_SIZE * 8.0f *
+ 1000.0f / (float)frame_length; /* bits/s */
+
+ bwest_str->rec_bw_inv = 1.0f /((float)bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+ }
+
+ ////////////////////////
+ arr_ts_diff = (float)(arr_ts - bwest_str->prev_rec_arr_ts);
+
+ if (send_ts_diff > 0 )
+ {
+ late_diff = arr_ts_diff - send_ts_diff;
+ }
+ else
+ {
+ late_diff = arr_ts_diff - (float)(16 * frame_length);
+ }
+
+ if((late_diff > 0) && !bwest_str->inWaitLatePkts)
+ {
+ bwest_str->numConsecLatePkts++;
+ bwest_str->consecLatency += late_diff;
+ }
+ else
+ {
+ bwest_str->numConsecLatePkts = 0;
+ bwest_str->consecLatency = 0;
+ }
+ if(bwest_str->numConsecLatePkts > 50)
+ {
+ float latencyMs = bwest_str->consecLatency/(FS/1000);
+ float averageLatencyMs = latencyMs / bwest_str->numConsecLatePkts;
+ delay_correction_factor = frame_length / (frame_length + averageLatencyMs);
+ immediate_set = 1;
+ bwest_str->inWaitLatePkts = (WebRtc_Word16)((bwest_str->consecLatency/(FS/1000)) / 30);// + 150;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ ///////////////////////////////////////////////
+
+
+
+ /* update only if previous packet was not lost */
+ if ( rtp_number == bwest_str->prev_rec_rtp_number + 1 )
+ {
+
+
+ if (!(bwest_str->hsn_detect_snd && bwest_str->hsn_detect_rec))
+ {
+ if ((arr_ts_diff > (float)(16 * frame_length)))
+ {
+ //1/2 second
+ if ((late_diff > 8000.0f) && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.7f;
+ bwest_str->in_wait_period = 55;
+ bwest_str->start_wait_period = arr_ts;
+ immediate_set = 1;
+ }
+ //320 ms
+ else if (late_diff > 5120.0f && !bwest_str->in_wait_period)
+ {
+ delay_correction_factor = 0.8f;
+ immediate_set = 1;
+ bwest_str->in_wait_period = 44;
+ bwest_str->start_wait_period = arr_ts;
+ }
+ }
+ }
+
+
+ if ((bwest_str->prev_rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ (rec_rtp_rate > bwest_str->rec_bw_avg) &&
+ !bwest_str->in_wait_period)
+ {
+ /* test if still in initiation period and increment counter */
+ if (bwest_str->count_tot_updates_rec++ > 99)
+ {
+ /* constant weight after initiation part */
+ weight = 0.01f;
+ }
+ else
+ {
+ /* weight decreases with number of updates */
+ weight = 1.0f / (float) bwest_str->count_tot_updates_rec;
+ }
+ /* Bottle Neck Estimation */
+
+ /* limit outliers */
+ /* if more than 25 ms too much */
+ if (arr_ts_diff > frame_length * FS/1000 + 400.0f)
+ {
+ // in samples, why 25ms??
+ arr_ts_diff = frame_length * FS/1000 + 400.0f;
+ }
+ if(arr_ts_diff < (frame_length * FS/1000) - 160.0f)
+ {
+ /* don't allow it to be less than frame rate - 10 ms */
+ arr_ts_diff = (float)frame_length * FS/1000 - 160.0f;
+ }
+
+ /* compute inverse receiving rate for last packet */
+ curr_bw_inv = arr_ts_diff / ((float)(pksize + HEADER_SIZE) *
+ 8.0f * FS); // (180+35)*8*16000 = 27.5 Mbit....
+
+
+ if(curr_bw_inv <
+ (1.0f / (MAX_ISAC_BW + bwest_str->rec_header_rate)))
+ {
+ // don't allow inv rate to be larger than MAX
+ curr_bw_inv = (1.0f /
+ (MAX_ISAC_BW + bwest_str->rec_header_rate));
+ }
+
+ /* update bottle neck rate estimate */
+ bwest_str->rec_bw_inv = weight * curr_bw_inv +
+ (1.0f - weight) * bwest_str->rec_bw_inv;
+
+ /* reset time-since-update counter */
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3 * FS;
+ bwest_str->num_pkts_rec = 0;
+
+ /* Jitter Estimation */
+ /* projected difference between arrival times */
+ t_diff_proj = ((float)(pksize + HEADER_SIZE) * 8.0f *
+ 1000.0f) / bwest_str->rec_bw_avg;
+
+
+ // difference between projected and actual
+ // arrival time differences
+ arr_time_noise = (float)(arr_ts_diff*1000.0f/FS) -
+ t_diff_proj;
+ arr_time_noise_abs = (float) fabs( arr_time_noise );
+
+ /* long term averaged absolute jitter */
+ bwest_str->rec_jitter = weight * arr_time_noise_abs +
+ (1.0f - weight) * bwest_str->rec_jitter;
+ if (bwest_str->rec_jitter > 10.0f)
+ {
+ bwest_str->rec_jitter = 10.0f;
+ }
+ /* short term averaged absolute jitter */
+ bwest_str->rec_jitter_short_term_abs = 0.05f *
+ arr_time_noise_abs + 0.95f *
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* short term averaged jitter */
+ bwest_str->rec_jitter_short_term = 0.05f * arr_time_noise +
+ 0.95f * bwest_str->rec_jitter_short_term;
+ }
+ }
+ }
+ else
+ {
+ // reset time-since-update counter when
+ // receiving the first 9 packets
+ bwest_str->last_update_ts = arr_ts;
+ bwest_str->last_reduction_ts = arr_ts + 3*FS;
+ bwest_str->num_pkts_rec = 0;
+
+ bwest_str->count_tot_updates_rec++;
+ }
+
+ /* limit minimum bottle neck rate */
+ if (bwest_str->rec_bw_inv > 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MIN_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ // limit maximum bitrate
+ if (bwest_str->rec_bw_inv < 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate))
+ {
+ bwest_str->rec_bw_inv = 1.0f / ((float)MAX_ISAC_BW +
+ bwest_str->rec_header_rate);
+ }
+
+ /* store frame length */
+ bwest_str->prev_frame_length = frame_length;
+
+ /* store far-side transmission rate */
+ bwest_str->prev_rec_rtp_rate = rec_rtp_rate;
+
+ /* store far-side RTP time stamp */
+ bwest_str->prev_rec_rtp_number = rtp_number;
+
+ // Replace bwest_str->rec_max_delay by the new
+ // value (atomic operation)
+ bwest_str->rec_max_delay = 3.0f * bwest_str->rec_jitter;
+
+ /* store send and arrival time stamp */
+ bwest_str->prev_rec_arr_ts = arr_ts ;
+ bwest_str->prev_rec_send_ts = send_ts;
+
+ /* Replace bwest_str->rec_bw by the new value (atomic operation) */
+ bwest_str->rec_bw = (WebRtc_Word32)(1.0f / bwest_str->rec_bw_inv -
+ bwest_str->rec_header_rate);
+
+ if (immediate_set)
+ {
+ bwest_str->rec_bw = (WebRtc_Word32) (delay_correction_factor *
+ (float) bwest_str->rec_bw);
+
+ if (bwest_str->rec_bw < (WebRtc_Word32) MIN_ISAC_BW)
+ {
+ bwest_str->rec_bw = (WebRtc_Word32) MIN_ISAC_BW;
+ }
+
+ bwest_str->rec_bw_avg = bwest_str->rec_bw +
+ bwest_str->rec_header_rate;
+
+ bwest_str->rec_bw_avg_Q = (float) bwest_str->rec_bw;
+
+ bwest_str->rec_jitter_short_term = 0.0f;
+
+ bwest_str->rec_bw_inv = 1.0f / (bwest_str->rec_bw +
+ bwest_str->rec_header_rate);
+
+ bwest_str->count_tot_updates_rec = 1;
+
+ immediate_set = 0;
+ bwest_str->consecLatency = 0;
+ bwest_str->numConsecLatePkts = 0;
+ }
+
+ return 0;
+}
+
+
+/* This function updates the send bottle neck rate */
+/* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+/* returns 0 if everything went fine, -1 otherwise */
+WebRtc_Word16 WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16 index,
+ enum IsacSamplingRate encoderSamplingFreq)
+{
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ if(encoderSamplingFreq == kIsacWideband)
+ {
+ if(index > 11)
+ {
+ index -= 12;
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableWb[index];
+ }
+ else
+ {
+ /* compute the BN estimate as decoded on the other side */
+ bwest_str->send_bw_avg = 0.9f * bwest_str->send_bw_avg +
+ 0.1f * kQRateTableSwb[index];
+ }
+
+ if (bwest_str->send_bw_avg > (float) 28000 && !bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k++;
+
+ if (bwest_str->num_consec_snt_pkts_over_30k >= 66)
+ {
+ //approx 2 seconds with 30ms frames
+ bwest_str->hsn_detect_snd = 1;
+ }
+ }
+ else if (!bwest_str->hsn_detect_snd)
+ {
+ bwest_str->num_consec_snt_pkts_over_30k = 0;
+ }
+ return 0;
+}
+
+// called when there is upper-band bit-stream to update jitter
+// statistics.
+WebRtc_Word16 WebRtcIsac_UpdateUplinkJitter(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word32 index)
+{
+ if((index < 0) || (index > 23))
+ {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ if(index > 0)
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MAX_ISAC_MD;
+ }
+ else
+ {
+ /* compute the jitter estimate as decoded on the other side */
+ bwest_str->send_max_delay_avg = 0.9f * bwest_str->send_max_delay_avg +
+ 0.1f * (float)MIN_ISAC_MD;
+ }
+
+ return 0;
+}
+
+
+
+// Returns the bandwidth/jitter estimation code (integer 0...23)
+// to put in the sending iSAC payload
+WebRtc_UWord16
+WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16* bottleneckIndex,
+ WebRtc_Word16* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq)
+{
+ float MaxDelay;
+ //WebRtc_UWord16 MaxDelayBit;
+
+ float rate;
+ float r;
+ float e1, e2;
+ const float weight = 0.1f;
+ const float* ptrQuantizationTable;
+ WebRtc_Word16 addJitterInfo;
+ WebRtc_Word16 minInd;
+ WebRtc_Word16 maxInd;
+ WebRtc_Word16 midInd;
+
+ /* Get Max Delay Bit */
+ /* get unquantized max delay */
+ MaxDelay = (float)WebRtcIsac_GetDownlinkMaxDelay(bwest_str);
+
+ if ( ((1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ MAX_ISAC_MD - MaxDelay) > (MaxDelay - (1.f-weight) *
+ bwest_str->rec_max_delay_avg_Q - weight * MIN_ISAC_MD) )
+ {
+ jitterInfo[0] = 0;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f - weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MIN_ISAC_MD;
+ }
+ else
+ {
+ jitterInfo[0] = 1;
+ /* update quantized average */
+ bwest_str->rec_max_delay_avg_Q =
+ (1.f-weight) * bwest_str->rec_max_delay_avg_Q + weight *
+ (float)MAX_ISAC_MD;
+ }
+
+ // Get unquantized rate.
+ rate = (float)WebRtcIsac_GetDownlinkBandwidth(bwest_str);
+
+ /* Get Rate Index */
+ if(decoderSamplingFreq == kIsacWideband)
+ {
+ ptrQuantizationTable = kQRateTableWb;
+ addJitterInfo = 1;
+ maxInd = 11;
+ }
+ else
+ {
+ ptrQuantizationTable = kQRateTableSwb;
+ addJitterInfo = 0;
+ maxInd = 23;
+ }
+
+ minInd = 0;
+ while(maxInd > minInd + 1)
+ {
+ midInd = (maxInd + minInd) >> 1;
+ if(rate > ptrQuantizationTable[midInd])
+ {
+ minInd = midInd;
+ }
+ else
+ {
+ maxInd = midInd;
+ }
+ }
+ // Chose the index which gives results an average which is closest
+ // to rate
+ r = (1 - weight) * bwest_str->rec_bw_avg_Q - rate;
+ e1 = weight * ptrQuantizationTable[minInd] + r;
+ e2 = weight * ptrQuantizationTable[maxInd] + r;
+ e1 = (e1 > 0)? e1:-e1;
+ e2 = (e2 > 0)? e2:-e2;
+ if(e1 < e2)
+ {
+ bottleneckIndex[0] = minInd;
+ }
+ else
+ {
+ bottleneckIndex[0] = maxInd;
+ }
+
+ bwest_str->rec_bw_avg_Q = (1 - weight) * bwest_str->rec_bw_avg_Q +
+ weight * ptrQuantizationTable[bottleneckIndex[0]];
+ bottleneckIndex[0] += jitterInfo[0] * 12 * addJitterInfo;
+
+ bwest_str->rec_bw_avg = (1 - weight) * bwest_str->rec_bw_avg + weight *
+ (rate + bwest_str->rec_header_rate);
+
+ return 0;
+}
+
+
+
+/* get the bottle neck rate from far side to here, as estimated on this side */
+WebRtc_Word32 WebRtcIsac_GetDownlinkBandwidth( const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 rec_bw;
+ float jitter_sign;
+ float bw_adjust;
+
+ /* create a value between -1.0 and 1.0 indicating "average sign" of jitter */
+ jitter_sign = bwest_str->rec_jitter_short_term /
+ bwest_str->rec_jitter_short_term_abs;
+
+ /* adjust bw proportionally to negative average jitter sign */
+ bw_adjust = 1.0f - jitter_sign * (0.15f + 0.15f * jitter_sign * jitter_sign);
+
+ /* adjust Rate if jitter sign is mostly constant */
+ rec_bw = (WebRtc_Word32)(bwest_str->rec_bw * bw_adjust);
+
+ /* limit range of bottle neck rate */
+ if (rec_bw < MIN_ISAC_BW)
+ {
+ rec_bw = MIN_ISAC_BW;
+ }
+ else if (rec_bw > MAX_ISAC_BW)
+ {
+ rec_bw = MAX_ISAC_BW;
+ }
+ return rec_bw;
+}
+
+/* Returns the max delay (in ms) */
+WebRtc_Word32
+WebRtcIsac_GetDownlinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 rec_max_delay;
+
+ rec_max_delay = (WebRtc_Word32)(bwest_str->rec_max_delay);
+
+ /* limit range of jitter estimate */
+ if (rec_max_delay < MIN_ISAC_MD)
+ {
+ rec_max_delay = MIN_ISAC_MD;
+ }
+ else if (rec_max_delay > MAX_ISAC_MD)
+ {
+ rec_max_delay = MAX_ISAC_MD;
+ }
+ return rec_max_delay;
+}
+
+/* get the bottle neck rate from here to far side, as estimated by far side */
+void
+WebRtcIsac_GetUplinkBandwidth(
+ const BwEstimatorstr* bwest_str,
+ WebRtc_Word32* bitRate)
+{
+ /* limit range of bottle neck rate */
+ if (bwest_str->send_bw_avg < MIN_ISAC_BW)
+ {
+ *bitRate = MIN_ISAC_BW;
+ }
+ else if (bwest_str->send_bw_avg > MAX_ISAC_BW)
+ {
+ *bitRate = MAX_ISAC_BW;
+ }
+ else
+ {
+ *bitRate = (WebRtc_Word32)(bwest_str->send_bw_avg);
+ }
+ return;
+}
+
+/* Returns the max delay value from the other side in ms */
+WebRtc_Word32
+WebRtcIsac_GetUplinkMaxDelay(const BwEstimatorstr *bwest_str)
+{
+ WebRtc_Word32 send_max_delay;
+
+ send_max_delay = (WebRtc_Word32)(bwest_str->send_max_delay_avg);
+
+ /* limit range of jitter estimate */
+ if (send_max_delay < MIN_ISAC_MD)
+ {
+ send_max_delay = MIN_ISAC_MD;
+ }
+ else if (send_max_delay > MAX_ISAC_MD)
+ {
+ send_max_delay = MAX_ISAC_MD;
+ }
+ return send_max_delay;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ * returns minimum payload size (bytes)
+ */
+int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,WebRtc_Word16 frequentLargePackets*/)
+{
+ double MinRate = 0.0;
+ int MinBytes;
+ double TransmissionTime;
+ int burstInterval = BURST_INTERVAL;
+
+ // first 10 packets @ low rate, then INIT_BURST_LEN packets @
+ // fixed rate of INIT_RATE bps
+ if (State->InitCounter > 0)
+ {
+ if (State->InitCounter-- <= INIT_BURST_LEN)
+ {
+ if(bandwidth == isac8kHz)
+ {
+ MinRate = INIT_RATE_WB;
+ }
+ else
+ {
+ MinRate = INIT_RATE_SWB;
+ }
+ }
+ else
+ {
+ MinRate = 0;
+ }
+ }
+ else
+ {
+ /* handle burst */
+ if (State->BurstCounter)
+ {
+ if (State->StillBuffered < (1.0 - 1.0/BURST_LEN) * DelayBuildUp)
+ {
+ /* max bps derived from BottleNeck and DelayBuildUp values */
+ MinRate = (1.0 + (FS/1000) * DelayBuildUp /
+ (double)(BURST_LEN * FrameSamples)) * BottleNeck;
+ }
+ else
+ {
+ // max bps derived from StillBuffered and DelayBuildUp
+ // values
+ MinRate = (1.0 + (FS/1000) * (DelayBuildUp -
+ State->StillBuffered) / (double)FrameSamples) * BottleNeck;
+ if (MinRate < 1.04 * BottleNeck)
+ {
+ MinRate = 1.04 * BottleNeck;
+ }
+ }
+ State->BurstCounter--;
+ }
+ }
+
+
+ /* convert rate from bits/second to bytes/packet */
+ MinBytes = (int) (MinRate * FrameSamples / (8.0 * FS));
+
+ /* StreamSize will be adjusted if less than MinBytes */
+ if (StreamSize < MinBytes)
+ {
+ StreamSize = MinBytes;
+ }
+
+ /* keep track of when bottle neck was last exceeded by at least 1% */
+ if (StreamSize * 8.0 * FS / FrameSamples > 1.01 * BottleNeck) {
+ if (State->PrevExceed) {
+ /* bottle_neck exceded twice in a row, decrease ExceedAgo */
+ State->ExceedAgo -= /*BURST_INTERVAL*/ burstInterval / (BURST_LEN - 1);
+ if (State->ExceedAgo < 0)
+ State->ExceedAgo = 0;
+ }
+ else
+ {
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ State->PrevExceed = 1;
+ }
+ }
+ else
+ {
+ State->PrevExceed = 0;
+ State->ExceedAgo += (FrameSamples * 1000) / FS; /* ms */
+ }
+
+ /* set burst flag if bottle neck not exceeded for long time */
+ if ((State->ExceedAgo > burstInterval) &&
+ (State->BurstCounter == 0))
+ {
+ if (State->PrevExceed)
+ {
+ State->BurstCounter = BURST_LEN - 1;
+ }
+ else
+ {
+ State->BurstCounter = BURST_LEN;
+ }
+ }
+
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ {
+ State->StillBuffered = 0.0;
+ }
+
+ return MinBytes;
+}
+
+
+/*
+ * update long-term average bitrate and amount of data in buffer
+ */
+void WebRtcIsac_UpdateRateModel(
+ RateModel *State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck) /* bottle neck rate; excl headers (bps) */
+{
+ double TransmissionTime;
+
+ /* avoid the initial "high-rate" burst */
+ State->InitCounter = 0;
+
+ /* Update buffer delay */
+ TransmissionTime = StreamSize * 8.0 * 1000.0 / BottleNeck; /* ms */
+ State->StillBuffered += TransmissionTime;
+ State->StillBuffered -= (FrameSamples * 1000) / FS; /* ms */
+ if (State->StillBuffered < 0.0)
+ State->StillBuffered = 0.0;
+
+}
+
+
+void WebRtcIsac_InitRateModel(
+ RateModel *State)
+{
+ State->PrevExceed = 0; /* boolean */
+ State->ExceedAgo = 0; /* ms */
+ State->BurstCounter = 0; /* packets */
+ State->InitCounter = INIT_BURST_LEN + 10; /* packets */
+ State->StillBuffered = 1.0; /* ms */
+}
+
+int WebRtcIsac_GetNewFrameLength(
+ double bottle_neck,
+ int current_framesamples)
+{
+ int new_framesamples;
+
+ const int Thld_20_30 = 20000;
+
+ //const int Thld_30_20 = 30000;
+ const int Thld_30_20 = 1000000; // disable 20 ms frames
+
+ const int Thld_30_60 = 18000;
+ //const int Thld_30_60 = 0; // disable 60 ms frames
+
+ const int Thld_60_30 = 27000;
+
+
+ new_framesamples = current_framesamples;
+
+ /* find new framelength */
+ switch(current_framesamples) {
+ case 320:
+ if (bottle_neck < Thld_20_30)
+ new_framesamples = 480;
+ break;
+ case 480:
+ if (bottle_neck < Thld_30_60)
+ new_framesamples = 960;
+ else if (bottle_neck > Thld_30_20)
+ new_framesamples = 320;
+ break;
+ case 960:
+ if (bottle_neck >= Thld_60_30)
+ new_framesamples = 480;
+ break;
+ }
+
+ return new_framesamples;
+}
+
+double WebRtcIsac_GetSnr(
+ double bottle_neck,
+ int framesamples)
+{
+ double s2nr;
+
+ const double a_20 = -30.0;
+ const double b_20 = 0.8;
+ const double c_20 = 0.0;
+
+ const double a_30 = -23.0;
+ const double b_30 = 0.48;
+ const double c_30 = 0.0;
+
+ const double a_60 = -23.0;
+ const double b_60 = 0.53;
+ const double c_60 = 0.0;
+
+
+ /* find new SNR value */
+ switch(framesamples) {
+ case 320:
+ s2nr = a_20 + b_20 * bottle_neck * 0.001 + c_20 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 480:
+ s2nr = a_30 + b_30 * bottle_neck * 0.001 + c_30 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ case 960:
+ s2nr = a_60 + b_60 * bottle_neck * 0.001 + c_60 * bottle_neck *
+ bottle_neck * 0.000001;
+ break;
+ default:
+ s2nr = 0;
+ }
+
+ return s2nr;
+
+}
diff --git a/src/mod/codecs/mod_isac/bandwidth_estimator.h b/src/mod/codecs/mod_isac/bandwidth_estimator.h
new file mode 100644
index 0000000000..5604d7bbbd
--- /dev/null
+++ b/src/mod/codecs/mod_isac/bandwidth_estimator.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * bandwidth_estimator.h
+ *
+ * This header file contains the API for the Bandwidth Estimator
+ * designed for iSAC.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_
+
+#include "structs.h"
+#include "settings.h"
+
+
+#define MIN_ISAC_BW 10000
+#define MIN_ISAC_BW_LB 10000
+#define MIN_ISAC_BW_UB 25000
+
+#define MAX_ISAC_BW 56000
+#define MAX_ISAC_BW_UB 32000
+#define MAX_ISAC_BW_LB 32000
+
+#define MIN_ISAC_MD 5
+#define MAX_ISAC_MD 25
+
+// assumed header size, in bytes; we don't know the exact number
+// (header compression may be used)
+#define HEADER_SIZE 35
+
+// Initial Frame-Size, in ms, for Wideband & Super-Wideband Mode
+#define INIT_FRAME_LEN_WB 60
+#define INIT_FRAME_LEN_SWB 30
+
+// Initial Bottleneck Estimate, in bits/sec, for
+// Wideband & Super-wideband mode
+#define INIT_BN_EST_WB 20e3f
+#define INIT_BN_EST_SWB 56e3f
+
+// Initial Header rate (header rate depends on frame-size),
+// in bits/sec, for Wideband & Super-Wideband mode.
+#define INIT_HDR_RATE_WB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_WB)
+#define INIT_HDR_RATE_SWB \
+ ((float)HEADER_SIZE * 8.0f * 1000.0f / (float)INIT_FRAME_LEN_SWB)
+
+// number of packets in a row for a high rate burst
+#define BURST_LEN 3
+
+// ms, max time between two full bursts
+#define BURST_INTERVAL 500
+
+// number of packets in a row for initial high rate burst
+#define INIT_BURST_LEN 5
+
+// bits/s, rate for the first BURST_LEN packets
+#define INIT_RATE_WB INIT_BN_EST_WB
+#define INIT_RATE_SWB INIT_BN_EST_SWB
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ /* This function initializes the struct */
+ /* to be called before using the struct for anything else */
+ /* returns 0 if everything went fine, -1 otherwise */
+ WebRtc_Word32 WebRtcIsac_InitBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+ /* This function updates the receiving estimate */
+ /* Parameters: */
+ /* rtp_number - value from RTP packet, from NetEq */
+ /* frame length - length of signal frame in ms, from iSAC decoder */
+ /* send_ts - value in RTP header giving send time in samples */
+ /* arr_ts - value given by timeGetTime() time of arrival in samples of packet from NetEq */
+ /* pksize - size of packet in bytes, from NetEq */
+ /* Index - integer (range 0...23) indicating bottle neck & jitter as estimated by other side */
+ /* returns 0 if everything went fine, -1 otherwise */
+ WebRtc_Word16 WebRtcIsac_UpdateBandwidthEstimator(
+ BwEstimatorstr* bwest_str,
+ const WebRtc_UWord16 rtp_number,
+ const WebRtc_Word32 frame_length,
+ const WebRtc_UWord32 send_ts,
+ const WebRtc_UWord32 arr_ts,
+ const WebRtc_Word32 pksize);
+
+ /* Update receiving estimates. Used when we only receive BWE index, no iSAC data packet. */
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkBwImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16 Index,
+ enum IsacSamplingRate encoderSamplingFreq);
+
+ /* Returns the bandwidth/jitter estimation code (integer 0...23) to put in the sending iSAC payload */
+ WebRtc_UWord16 WebRtcIsac_GetDownlinkBwJitIndexImpl(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word16* bottleneckIndex,
+ WebRtc_Word16* jitterInfo,
+ enum IsacSamplingRate decoderSamplingFreq);
+
+ /* Returns the bandwidth estimation (in bps) */
+ WebRtc_Word32 WebRtcIsac_GetDownlinkBandwidth(
+ const BwEstimatorstr *bwest_str);
+
+ /* Returns the max delay (in ms) */
+ WebRtc_Word32 WebRtcIsac_GetDownlinkMaxDelay(
+ const BwEstimatorstr *bwest_str);
+
+ /* Returns the bandwidth that iSAC should send with in bps */
+ void WebRtcIsac_GetUplinkBandwidth(
+ const BwEstimatorstr* bwest_str,
+ WebRtc_Word32* bitRate);
+
+ /* Returns the max delay value from the other side in ms */
+ WebRtc_Word32 WebRtcIsac_GetUplinkMaxDelay(
+ const BwEstimatorstr *bwest_str);
+
+
+ /*
+ * update amount of data in bottle neck buffer and burst handling
+ * returns minimum payload size (bytes)
+ */
+ int WebRtcIsac_GetMinBytes(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameLen, /* ms per frame */
+ const double BottleNeck, /* bottle neck rate; excl headers (bps) */
+ const double DelayBuildUp, /* max delay from bottleneck buffering (ms) */
+ enum ISACBandwidth bandwidth
+ /*,WebRtc_Word16 frequentLargePackets*/);
+
+ /*
+ * update long-term average bitrate and amount of data in buffer
+ */
+ void WebRtcIsac_UpdateRateModel(
+ RateModel* State,
+ int StreamSize, /* bytes in bitstream */
+ const int FrameSamples, /* samples per frame */
+ const double BottleNeck); /* bottle neck rate; excl headers (bps) */
+
+
+ void WebRtcIsac_InitRateModel(
+ RateModel *State);
+
+ /* Returns the new framelength value (input argument: bottle_neck) */
+ int WebRtcIsac_GetNewFrameLength(
+ double bottle_neck,
+ int current_framelength);
+
+ /* Returns the new SNR value (input argument: bottle_neck) */
+ double WebRtcIsac_GetSnr(
+ double bottle_neck,
+ int new_framelength);
+
+
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkJitter(
+ BwEstimatorstr* bwest_str,
+ WebRtc_Word32 index);
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_BANDWIDTH_ESTIMATOR_H_ */
diff --git a/src/mod/codecs/mod_isac/codec.h b/src/mod/codecs/mod_isac/codec.h
new file mode 100644
index 0000000000..6af27ea9e0
--- /dev/null
+++ b/src/mod/codecs/mod_isac/codec.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * codec.h
+ *
+ * This header file contains the calls to the internal encoder
+ * and decoder functions.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_
+
+#include "structs.h"
+
+int WebRtcIsac_EstimateBandwidth(
+ BwEstimatorstr* bwest_str,
+ Bitstr* streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate);
+
+int WebRtcIsac_DecodeLb(
+ float* signal_out,
+ ISACLBDecStruct* ISACdec_obj,
+ WebRtc_Word16* current_framesamples,
+ WebRtc_Word16 isRCUPayload);
+
+int WebRtcIsac_DecodeRcuLb(
+ float* signal_out,
+ ISACLBDecStruct* ISACdec_obj,
+ WebRtc_Word16* current_framesamples);
+
+int WebRtcIsac_EncodeLb(
+ float* in,
+ ISACLBEncStruct* ISACencLB_obj,
+ WebRtc_Word16 codingMode,
+ WebRtc_Word16 bottleneckIndex);
+
+int WebRtcIsac_EncodeStoredDataLb(
+ const ISAC_SaveEncData_t* ISACSavedEnc_obj,
+ Bitstr* ISACBitStr_obj,
+ int BWnumber,
+ float scale);
+
+
+int WebRtcIsac_EncodeStoredDataUb12(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo,
+ float scale);
+
+int WebRtcIsac_EncodeStoredDataUb16(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo,
+ float scale);
+
+
+WebRtc_Word16 WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+ Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth);
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bit-rate in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bit-rate allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bit-rate allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+WebRtc_Word16
+WebRtcIsac_RateAllocation(
+ WebRtc_Word32 inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb16()
+ *
+ * Decode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb16(
+ float* signal_out,
+ ISACUBDecStruct* ISACdec_obj,
+ WebRtc_Word16 isRCUPayload);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeUb12()
+ *
+ * Decode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band decoder object. The
+ * bit-stream is stored inside the decoder object.
+ *
+ * Output:
+ * -signal_out : decoded audio, 480 samples 30 ms.
+ *
+ * Return value : >0 number of decoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_DecodeUb12(
+ float* signal_out,
+ ISACUBDecStruct* ISACdec_obj,
+ WebRtc_Word16 isRCUPayload);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb16()
+ *
+ * Encode the upper-band if the codec is in 0-16 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb16(
+ float* in,
+ ISACUBEncStruct* ISACenc_obj,
+ WebRtc_Word32 jitterInfo);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeUb12()
+ *
+ * Encode the upper-band if the codec is in 0-12 kHz mode.
+ *
+ * Input:
+ * -in : upper-band audio, 160 samples (10 ms).
+ *
+ * Input/Output:
+ * -ISACdec_obj : pointer to the upper-band encoder object. The
+ * bit-stream is stored inside the encoder object.
+ *
+ * Return value : >0 number of encoded bytes.
+ * <0 if an error occurred.
+ */
+int WebRtcIsac_EncodeUb12(
+ float* in,
+ ISACUBEncStruct* ISACenc_obj,
+ WebRtc_Word32 jitterInfo);
+
+/************************** initialization functions *************************/
+
+void WebRtcIsac_InitMasking(MaskFiltstr *maskdata);
+
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr *prefiltdata);
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata);
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr *pitchfiltdata);
+
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct *State);
+
+
+/**************************** transform functions ****************************/
+
+void WebRtcIsac_InitTransform();
+
+void WebRtcIsac_Time2Spec(double *inre1,
+ double *inre2,
+ WebRtc_Word16 *outre,
+ WebRtc_Word16 *outim,
+ FFTstr *fftstr_obj);
+
+void WebRtcIsac_Spec2time(double *inre,
+ double *inim,
+ double *outre1,
+ double *outre2,
+ FFTstr *fftstr_obj);
+
+
+/******************************* filter functions ****************************/
+
+void WebRtcIsac_AllPoleFilter(double *InOut,
+ double *Coef,
+ int lengthInOut,
+ int orderCoef);
+
+void WebRtcIsac_AllZeroFilter(double *In,
+ double *Coef,
+ int lengthInOut,
+ int orderCoef,
+ double *Out);
+
+void WebRtcIsac_ZeroPoleFilter(double *In,
+ double *ZeroCoef,
+ double *PoleCoef,
+ int lengthInOut,
+ int orderCoef,
+ double *Out);
+
+
+/***************************** filterbank functions **************************/
+
+void WebRtcIsac_SplitAndFilter(double *in,
+ double *LP,
+ double *HP,
+ double *LP_la,
+ double *HP_la,
+ PreFiltBankstr *prefiltdata);
+
+
+void WebRtcIsac_FilterAndCombine(double *InLP,
+ double *InHP,
+ double *Out,
+ PostFiltBankstr *postfiltdata);
+
+
+
+void WebRtcIsac_SplitAndFilterFloat(float *in,
+ float *LP,
+ float *HP,
+ double *LP_la,
+ double *HP_la,
+ PreFiltBankstr *prefiltdata);
+
+
+void WebRtcIsac_FilterAndCombineFloat(float *InLP,
+ float *InHP,
+ float *Out,
+ PostFiltBankstr *postfiltdata);
+
+
+/************************* normalized lattice filters ************************/
+
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+ float *stateF,
+ float *stateG,
+ float *lat_in,
+ double *filtcoeflo,
+ double *lat_out);
+
+void WebRtcIsac_NormLatticeFilterAr(int orderCoef,
+ float *stateF,
+ float *stateG,
+ double *lat_in,
+ double *lo_filt_coef,
+ float *lat_out);
+
+void WebRtcIsac_Dir2Lat(double *a,
+ int orderCoef,
+ float *sth,
+ float *cth);
+
+void WebRtcIsac_AutoCorr(double *r,
+ const double *x,
+ int N,
+ int order);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CODEC_H_ */
diff --git a/src/mod/codecs/mod_isac/complex_bit_reverse.c b/src/mod/codecs/mod_isac/complex_bit_reverse.c
new file mode 100644
index 0000000000..85c76f8283
--- /dev/null
+++ b/src/mod/codecs/mod_isac/complex_bit_reverse.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_ComplexBitReverse().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_ComplexBitReverse(WebRtc_Word16 frfi[], int stages)
+{
+ int mr, nn, n, l, m;
+ WebRtc_Word16 tr, ti;
+
+ n = 1 << stages;
+
+ mr = 0;
+ nn = n - 1;
+
+ // decimation in time - re-order data
+ for (m = 1; m <= nn; ++m)
+ {
+ l = n;
+ do
+ {
+ l >>= 1;
+ } while (mr + l > nn);
+ mr = (mr & (l - 1)) + l;
+
+ if (mr <= m)
+ continue;
+
+ tr = frfi[2 * m];
+ frfi[2 * m] = frfi[2 * mr];
+ frfi[2 * mr] = tr;
+
+ ti = frfi[2 * m + 1];
+ frfi[2 * m + 1] = frfi[2 * mr + 1];
+ frfi[2 * mr + 1] = ti;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/complex_fft.c b/src/mod/codecs/mod_isac/complex_fft.c
new file mode 100644
index 0000000000..1e8503c245
--- /dev/null
+++ b/src/mod/codecs/mod_isac/complex_fft.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_ComplexFFT().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define CFFTSFT 14
+#define CFFTRND 1
+#define CFFTRND2 16384
+
+#define CIFFTSFT 14
+#define CIFFTRND 1
+
+static const WebRtc_Word16 kSinTable1024[] = {
+ 0, 201, 402, 603, 804, 1005, 1206, 1406,
+ 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011,
+ 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608,
+ 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195,
+ 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766,
+ 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319,
+ 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849,
+ 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353,
+ 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827,
+ 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268,
+ 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672,
+ 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036,
+ 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357,
+ 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631,
+ 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855,
+ 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027,
+ 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143,
+ 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201,
+ 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198,
+ 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132,
+ 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001,
+ 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802,
+ 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534,
+ 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195,
+ 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783,
+ 30851, 30918, 30984, 31049,
+ 31113, 31175, 31236, 31297,
+ 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735,
+ 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097,
+ 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382,
+ 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588,
+ 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717,
+ 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766,
+ 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736,
+ 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628,
+ 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441,
+ 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176,
+ 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833,
+ 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413,
+ 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918,
+ 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349,
+ 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706,
+ 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992,
+ 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208,
+ 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355,
+ 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437,
+ 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456,
+ 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413,
+ 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311,
+ 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153,
+ 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942,
+ 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680,
+ 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371,
+ 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017,
+ 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623,
+ 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191,
+ 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724,
+ 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227,
+ 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703,
+ 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156,
+ 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589,
+ 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006,
+ 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411,
+ 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808,
+ 1607, 1406, 1206, 1005, 804, 603, 402, 201,
+ 0, -201, -402, -603, -804, -1005, -1206, -1406,
+ -1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011,
+ -3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608,
+ -4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195,
+ -6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766,
+ -7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319,
+ -9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849,
+ -11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353,
+ -12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827,
+ -14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268,
+ -15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672,
+ -16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036,
+ -18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357,
+ -19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631,
+ -20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855,
+ -22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027,
+ -23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143,
+ -24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201,
+ -25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198,
+ -26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132,
+ -27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001,
+ -28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802,
+ -28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534,
+ -29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195,
+ -30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783,
+ -30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297,
+ -31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735,
+ -31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097,
+ -32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382,
+ -32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588,
+ -32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717,
+ -32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766,
+ -32767, -32766, -32764, -32761, -32757, -32751, -32744, -32736,
+ -32727, -32717, -32705, -32692, -32678, -32662, -32646, -32628,
+ -32609, -32588, -32567, -32544, -32520, -32495, -32468, -32441,
+ -32412, -32382, -32350, -32318, -32284, -32249, -32213, -32176,
+ -32137, -32097, -32056, -32014, -31970, -31926, -31880, -31833,
+ -31785, -31735, -31684, -31633, -31580, -31525, -31470, -31413,
+ -31356, -31297, -31236, -31175, -31113, -31049, -30984, -30918,
+ -30851, -30783, -30713, -30643, -30571, -30498, -30424, -30349,
+ -30272, -30195, -30116, -30036, -29955, -29873, -29790, -29706,
+ -29621, -29534, -29446, -29358, -29268, -29177, -29085, -28992,
+ -28897, -28802, -28706, -28608, -28510, -28410, -28309, -28208,
+ -28105, -28001, -27896, -27790, -27683, -27575, -27466, -27355,
+ -27244, -27132, -27019, -26905, -26789, -26673, -26556, -26437,
+ -26318, -26198, -26077, -25954, -25831, -25707, -25582, -25456,
+ -25329, -25201, -25072, -24942, -24811, -24679, -24546, -24413,
+ -24278, -24143, -24006, -23869, -23731, -23592, -23452, -23311,
+ -23169, -23027, -22883, -22739, -22594, -22448, -22301, -22153,
+ -22004, -21855, -21705, -21554, -21402, -21249, -21096, -20942,
+ -20787, -20631, -20474, -20317, -20159, -20000, -19840, -19680,
+ -19519, -19357, -19194, -19031, -18867, -18702, -18537, -18371,
+ -18204, -18036, -17868, -17699, -17530, -17360, -17189, -17017,
+ -16845, -16672, -16499, -16325, -16150, -15975, -15799, -15623,
+ -15446, -15268, -15090, -14911, -14732, -14552, -14372, -14191,
+ -14009, -13827, -13645, -13462, -13278, -13094, -12909, -12724,
+ -12539, -12353, -12166, -11980, -11792, -11604, -11416, -11227,
+ -11038, -10849, -10659, -10469, -10278, -10087, -9895, -9703,
+ -9511, -9319, -9126, -8932, -8739, -8545, -8351, -8156,
+ -7961, -7766, -7571, -7375, -7179, -6982, -6786, -6589,
+ -6392, -6195, -5997, -5799, -5601, -5403, -5205, -5006,
+ -4807, -4608, -4409, -4210, -4011, -3811, -3611, -3411,
+ -3211, -3011, -2811, -2610, -2410, -2209, -2009, -1808,
+ -1607, -1406, -1206, -1005, -804, -603, -402, -201
+};
+
+int WebRtcSpl_ComplexFFT(WebRtc_Word16 frfi[], int stages, int mode)
+{
+ int i, j, l, k, istep, n, m;
+ WebRtc_Word16 wr, wi;
+ WebRtc_Word32 tr32, ti32, qr32, qi32;
+
+ /* The 1024-value is a constant given from the size of kSinTable1024[],
+ * and should not be changed depending on the input parameter 'stages'
+ */
+ n = 1 << stages;
+ if (n > 1024)
+ return -1;
+
+ l = 1;
+ k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
+ depending on the input parameter 'stages' */
+
+ if (mode == 0)
+ {
+ // mode==0: Low-complexity and Low-accuracy mode
+ while (l < n)
+ {
+ istep = l << 1;
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = -kSinTable1024[j];
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1])), 15);
+
+ ti32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j])), 15);
+
+ qr32 = (WebRtc_Word32)frfi[2 * i];
+ qi32 = (WebRtc_Word32)frfi[2 * i + 1];
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, 1);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, 1);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, 1);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, 1);
+ }
+ }
+
+ --k;
+ l = istep;
+
+ }
+
+ } else
+ {
+ // mode==1: High-complexity and High-accuracy mode
+ while (l < n)
+ {
+ istep = l << 1;
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = -kSinTable1024[j];
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+ WebRtc_Word32 wri;
+ WebRtc_Word32 frfi_r;
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
+ "r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
+#endif
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
+ "r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
+ __asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
+ "r"(wri), "r"(frfi_r), "r"(CFFTRND));
+ __asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
+ "r"(wri), "r"(frfi_r), "r"(CFFTRND));
+
+#else
+ tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CFFTRND;
+
+ ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CFFTRND;
+#endif
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CFFTSFT);
+ ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CFFTSFT);
+
+ qr32 = ((WebRtc_Word32)frfi[2 * i]) << CFFTSFT;
+ qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CFFTSFT;
+
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qr32 - tr32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 - ti32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qr32 + tr32 + CFFTRND2), 1 + CFFTSFT);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 + ti32 + CFFTRND2), 1 + CFFTSFT);
+ }
+ }
+
+ --k;
+ l = istep;
+ }
+ }
+ return 0;
+}
+
+int WebRtcSpl_ComplexIFFT(WebRtc_Word16 frfi[], int stages, int mode)
+{
+ int i, j, l, k, istep, n, m, scale, shift;
+ WebRtc_Word16 wr, wi;
+ WebRtc_Word32 tr32, ti32, qr32, qi32;
+ WebRtc_Word32 tmp32, round2;
+
+ /* The 1024-value is a constant given from the size of kSinTable1024[],
+ * and should not be changed depending on the input parameter 'stages'
+ */
+ n = 1 << stages;
+ if (n > 1024)
+ return -1;
+
+ scale = 0;
+
+ l = 1;
+ k = 10 - 1; /* Constant for given kSinTable1024[]. Do not change
+ depending on the input parameter 'stages' */
+
+ while (l < n)
+ {
+ // variable scaling, depending upon data
+ shift = 0;
+ round2 = 8192;
+
+ tmp32 = (WebRtc_Word32)WebRtcSpl_MaxAbsValueW16(frfi, 2 * n);
+ if (tmp32 > 13573)
+ {
+ shift++;
+ scale++;
+ round2 <<= 1;
+ }
+ if (tmp32 > 27146)
+ {
+ shift++;
+ scale++;
+ round2 <<= 1;
+ }
+
+ istep = l << 1;
+
+ if (mode == 0)
+ {
+ // mode==0: Low-complexity and Low-accuracy mode
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = kSinTable1024[j];
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+ tr32 = WEBRTC_SPL_RSHIFT_W32((WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j], 0)
+ - WEBRTC_SPL_MUL_16_16_RSFT(wi, frfi[2 * j + 1], 0)), 15);
+
+ ti32 = WEBRTC_SPL_RSHIFT_W32(
+ (WEBRTC_SPL_MUL_16_16_RSFT(wr, frfi[2 * j + 1], 0)
+ + WEBRTC_SPL_MUL_16_16_RSFT(wi,frfi[2*j],0)), 15);
+
+ qr32 = (WebRtc_Word32)frfi[2 * i];
+ qi32 = (WebRtc_Word32)frfi[2 * i + 1];
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 - tr32, shift);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 - ti32, shift);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qr32 + tr32, shift);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(qi32 + ti32, shift);
+ }
+ }
+ } else
+ {
+ // mode==1: High-complexity and High-accuracy mode
+
+ for (m = 0; m < l; ++m)
+ {
+ j = m << k;
+
+ /* The 256-value is a constant given as 1/4 of the size of
+ * kSinTable1024[], and should not be changed depending on the input
+ * parameter 'stages'. It will result in 0 <= j < N_SINE_WAVE/2
+ */
+ wr = kSinTable1024[j + 256];
+ wi = kSinTable1024[j];
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+ WebRtc_Word32 wri;
+ WebRtc_Word32 frfi_r;
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(wri) :
+ "r"((WebRtc_Word32)wr), "r"((WebRtc_Word32)wi));
+#endif
+
+ for (i = m; i < n; i += istep)
+ {
+ j = i + l;
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(frfi_r) :
+ "r"((WebRtc_Word32)frfi[2*j]), "r"((WebRtc_Word32)frfi[2*j +1]));
+ __asm__("smlsd %0, %1, %2, %3" : "=r"(tr32) :
+ "r"(wri), "r"(frfi_r), "r"(CIFFTRND));
+ __asm__("smladx %0, %1, %2, %3" : "=r"(ti32) :
+ "r"(wri), "r"(frfi_r), "r"(CIFFTRND));
+#else
+
+ tr32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j])
+ - WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j + 1]) + CIFFTRND;
+
+ ti32 = WEBRTC_SPL_MUL_16_16(wr, frfi[2 * j + 1])
+ + WEBRTC_SPL_MUL_16_16(wi, frfi[2 * j]) + CIFFTRND;
+#endif
+ tr32 = WEBRTC_SPL_RSHIFT_W32(tr32, 15 - CIFFTSFT);
+ ti32 = WEBRTC_SPL_RSHIFT_W32(ti32, 15 - CIFFTSFT);
+
+ qr32 = ((WebRtc_Word32)frfi[2 * i]) << CIFFTSFT;
+ qi32 = ((WebRtc_Word32)frfi[2 * i + 1]) << CIFFTSFT;
+
+ frfi[2 * j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 - tr32+round2),
+ shift+CIFFTSFT);
+ frfi[2 * j + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 - ti32 + round2), shift + CIFFTSFT);
+ frfi[2 * i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((qr32 + tr32 + round2),
+ shift + CIFFTSFT);
+ frfi[2 * i + 1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(
+ (qi32 + ti32 + round2), shift + CIFFTSFT);
+ }
+ }
+
+ }
+ --k;
+ l = istep;
+ }
+ return scale;
+}
diff --git a/src/mod/codecs/mod_isac/copy_set_operations.c b/src/mod/codecs/mod_isac/copy_set_operations.c
new file mode 100644
index 0000000000..8247337754
--- /dev/null
+++ b/src/mod/codecs/mod_isac/copy_set_operations.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the implementation of functions
+ * WebRtcSpl_MemSetW16()
+ * WebRtcSpl_MemSetW32()
+ * WebRtcSpl_MemCpyReversedOrder()
+ * WebRtcSpl_CopyFromEndW16()
+ * WebRtcSpl_ZerosArrayW16()
+ * WebRtcSpl_ZerosArrayW32()
+ * WebRtcSpl_OnesArrayW16()
+ * WebRtcSpl_OnesArrayW32()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include
+#include "signal_processing_library.h"
+
+
+void WebRtcSpl_MemSetW16(WebRtc_Word16 *ptr, WebRtc_Word16 set_value, int length)
+{
+ int j;
+ WebRtc_Word16 *arrptr = ptr;
+
+ for (j = length; j > 0; j--)
+ {
+ *arrptr++ = set_value;
+ }
+}
+
+void WebRtcSpl_MemSetW32(WebRtc_Word32 *ptr, WebRtc_Word32 set_value, int length)
+{
+ int j;
+ WebRtc_Word32 *arrptr = ptr;
+
+ for (j = length; j > 0; j--)
+ {
+ *arrptr++ = set_value;
+ }
+}
+
+void WebRtcSpl_MemCpyReversedOrder(WebRtc_Word16* dest, WebRtc_Word16* source, int length)
+{
+ int j;
+ WebRtc_Word16* destPtr = dest;
+ WebRtc_Word16* sourcePtr = source;
+
+ for (j = 0; j < length; j++)
+ {
+ *destPtr-- = *sourcePtr++;
+ }
+}
+
+WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16 *vector_in,
+ WebRtc_Word16 length,
+ WebRtc_Word16 samples,
+ WebRtc_Word16 *vector_out)
+{
+ // Copy the last of the input vector to vector_out
+ WEBRTC_SPL_MEMCPY_W16(vector_out, &vector_in[length - samples], samples);
+
+ return samples;
+}
+
+WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtcSpl_MemSetW16(vector, 0, length);
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtcSpl_MemSetW32(vector, 0, length);
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_OnesArrayW16(WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word16 *tmpvec = vector;
+ for (i = 0; i < length; i++)
+ {
+ *tmpvec++ = 1;
+ }
+ return length;
+}
+
+WebRtc_Word16 WebRtcSpl_OnesArrayW32(WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word32 *tmpvec = vector;
+ for (i = 0; i < length; i++)
+ {
+ *tmpvec++ = 1;
+ }
+ return length;
+}
diff --git a/src/mod/codecs/mod_isac/crc.c b/src/mod/codecs/mod_isac/crc.c
new file mode 100644
index 0000000000..098e4b7a69
--- /dev/null
+++ b/src/mod/codecs/mod_isac/crc.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "crc.h"
+#include
+#include "signal_processing_library.h"
+
+#define POLYNOMIAL 0x04c11db7L
+
+
+static const WebRtc_UWord32 kCrcTable[256] = {
+ 0, 0x4c11db7, 0x9823b6e, 0xd4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x18aeb13, 0x54bf6a4,
+ 0x808d07d, 0xcc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x315d626, 0x7d4cb91, 0xa97ed48, 0xe56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x29f3d35, 0x65e2082, 0xb1d065b, 0xfdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - bitstream : payload bitstream
+ * - len_bitstream_in_bytes : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsac_GetCrc(const WebRtc_Word16* bitstream,
+ WebRtc_Word16 len_bitstream_in_bytes,
+ WebRtc_UWord32* crc)
+{
+ WebRtc_UWord8* bitstream_ptr_uw8;
+ WebRtc_UWord32 crc_state;
+ int byte_cntr;
+ int crc_tbl_indx;
+
+ /* Sanity Check. */
+ if (bitstream == NULL) {
+ return -1;
+ }
+ /* cast to UWord8 pointer */
+ bitstream_ptr_uw8 = (WebRtc_UWord8 *)bitstream;
+
+ /* initialize */
+ crc_state = 0xFFFFFFFF;
+
+ for (byte_cntr = 0; byte_cntr < len_bitstream_in_bytes; byte_cntr++) {
+ crc_tbl_indx = (WEBRTC_SPL_RSHIFT_U32(crc_state, 24) ^
+ bitstream_ptr_uw8[byte_cntr]) & 0xFF;
+ crc_state = WEBRTC_SPL_LSHIFT_U32(crc_state, 8) ^ kCrcTable[crc_tbl_indx];
+ }
+
+ *crc = ~crc_state;
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/crc.h b/src/mod/codecs/mod_isac/crc.h
new file mode 100644
index 0000000000..015127894b
--- /dev/null
+++ b/src/mod/codecs/mod_isac/crc.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * crc.h
+ *
+ * Checksum functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
+
+#include "typedefs.h"
+
+/****************************************************************************
+ * WebRtcIsac_GetCrc(...)
+ *
+ * This function returns a 32 bit CRC checksum of a bit stream
+ *
+ * Input:
+ * - encoded : payload bit stream
+ * - no_of_word8s : number of 8-bit words in the bit stream
+ *
+ * Output:
+ * - crc : checksum
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsac_GetCrc(
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16 no_of_word8s,
+ WebRtc_UWord32* crc);
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_ */
diff --git a/src/mod/codecs/mod_isac/cross_correlation.c b/src/mod/codecs/mod_isac/cross_correlation.c
new file mode 100644
index 0000000000..726a74967b
--- /dev/null
+++ b/src/mod/codecs/mod_isac/cross_correlation.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_CrossCorrelation().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+/* TODO(kma): Clean up the code in this file, and break it up for
+ * various platforms (Xscale, ARM/Neon etc.).
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_CrossCorrelation(WebRtc_Word32* cross_correlation, WebRtc_Word16* seq1,
+ WebRtc_Word16* seq2, WebRtc_Word16 dim_seq,
+ WebRtc_Word16 dim_cross_correlation,
+ WebRtc_Word16 right_shifts,
+ WebRtc_Word16 step_seq2)
+{
+ int i, j;
+ WebRtc_Word16* seq1Ptr;
+ WebRtc_Word16* seq2Ptr;
+ WebRtc_Word32* CrossCorrPtr;
+
+#ifdef _XSCALE_OPT_
+
+#ifdef _WIN32
+#pragma message("NOTE: _XSCALE_OPT_ optimizations are used (overrides _ARM_OPT_ and requires /QRxscale compiler flag)")
+#endif
+
+ __int64 macc40;
+
+ int iseq1[250];
+ int iseq2[250];
+ int iseq3[250];
+ int * iseq1Ptr;
+ int * iseq2Ptr;
+ int * iseq3Ptr;
+ int len, i_len;
+
+ seq1Ptr = seq1;
+ iseq1Ptr = iseq1;
+ for(i = 0; i < ((dim_seq + 1) >> 1); i++)
+ {
+ *iseq1Ptr = (unsigned short)*seq1Ptr++;
+ *iseq1Ptr++ |= (WebRtc_Word32)*seq1Ptr++ << 16;
+
+ }
+
+ if(dim_seq%2)
+ {
+ *(iseq1Ptr-1) &= 0x0000ffff;
+ }
+ *iseq1Ptr = 0;
+ iseq1Ptr++;
+ *iseq1Ptr = 0;
+ iseq1Ptr++;
+ *iseq1Ptr = 0;
+
+ if(step_seq2 < 0)
+ {
+ seq2Ptr = seq2 - dim_cross_correlation + 1;
+ CrossCorrPtr = &cross_correlation[dim_cross_correlation - 1];
+ }
+ else
+ {
+ seq2Ptr = seq2;
+ CrossCorrPtr = cross_correlation;
+ }
+
+ len = dim_seq + dim_cross_correlation - 1;
+ i_len = (len + 1) >> 1;
+ iseq2Ptr = iseq2;
+
+ iseq3Ptr = iseq3;
+ for(i = 0; i < i_len; i++)
+ {
+ *iseq2Ptr = (unsigned short)*seq2Ptr++;
+ *iseq3Ptr = (unsigned short)*seq2Ptr;
+ *iseq2Ptr++ |= (WebRtc_Word32)*seq2Ptr++ << 16;
+ *iseq3Ptr++ |= (WebRtc_Word32)*seq2Ptr << 16;
+ }
+
+ if(len % 2)
+ {
+ iseq2[i_len - 1] &= 0x0000ffff;
+ iseq3[i_len - 1] = 0;
+ }
+ else
+ iseq3[i_len - 1] &= 0x0000ffff;
+
+ iseq2[i_len] = 0;
+ iseq3[i_len] = 0;
+ iseq2[i_len + 1] = 0;
+ iseq3[i_len + 1] = 0;
+ iseq2[i_len + 2] = 0;
+ iseq3[i_len + 2] = 0;
+
+ // Set pointer to start value
+ iseq2Ptr = iseq2;
+ iseq3Ptr = iseq3;
+
+ i_len = (dim_seq + 7) >> 3;
+ for (i = 0; i < dim_cross_correlation; i++)
+ {
+
+ iseq1Ptr = iseq1;
+
+ macc40 = 0;
+
+ _WriteCoProcessor(macc40, 0);
+
+ if((i & 1))
+ {
+ iseq3Ptr = iseq3 + (i >> 1);
+ for (j = i_len; j > 0; j--)
+ {
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq3Ptr++);
+ }
+ }
+ else
+ {
+ iseq2Ptr = iseq2 + (i >> 1);
+ for (j = i_len; j > 0; j--)
+ {
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
+ _SmulAddPack_2SW_ACC(*iseq1Ptr++, *iseq2Ptr++);
+ }
+
+ }
+
+ macc40 = _ReadCoProcessor(0);
+ *CrossCorrPtr = (WebRtc_Word32)(macc40 >> right_shifts);
+ CrossCorrPtr += step_seq2;
+ }
+#else // #ifdef _XSCALE_OPT_
+#ifdef _ARM_OPT_
+ WebRtc_Word16 dim_seq8 = (dim_seq >> 3) << 3;
+#endif
+
+ CrossCorrPtr = cross_correlation;
+
+ for (i = 0; i < dim_cross_correlation; i++)
+ {
+ // Set the pointer to the static vector, set the pointer to the sliding vector
+ // and initialize cross_correlation
+ seq1Ptr = seq1;
+ seq2Ptr = seq2 + (step_seq2 * i);
+ (*CrossCorrPtr) = 0;
+
+#ifndef _ARM_OPT_
+#ifdef _WIN32
+#pragma message("NOTE: default implementation is used")
+#endif
+ // Perform the cross correlation
+ for (j = 0; j < dim_seq; j++)
+ {
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr), right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ }
+#else
+#ifdef _WIN32
+#pragma message("NOTE: _ARM_OPT_ optimizations are used")
+#endif
+ if (right_shifts == 0)
+ {
+ // Perform the optimized cross correlation
+ for (j = 0; j < dim_seq8; j = j + 8)
+ {
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ }
+
+ for (j = dim_seq8; j < dim_seq; j++)
+ {
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16((*seq1Ptr), (*seq2Ptr));
+ seq1Ptr++;
+ seq2Ptr++;
+ }
+ }
+ else // right_shifts != 0
+
+ {
+ // Perform the optimized cross correlation
+ for (j = 0; j < dim_seq8; j = j + 8)
+ {
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ }
+
+ for (j = dim_seq8; j < dim_seq; j++)
+ {
+ (*CrossCorrPtr) += WEBRTC_SPL_MUL_16_16_RSFT((*seq1Ptr), (*seq2Ptr),
+ right_shifts);
+ seq1Ptr++;
+ seq2Ptr++;
+ }
+ }
+#endif
+ CrossCorrPtr++;
+ }
+#endif
+}
diff --git a/src/mod/codecs/mod_isac/decode.c b/src/mod/codecs/mod_isac/decode.c
new file mode 100644
index 0000000000..25634b0a89
--- /dev/null
+++ b/src/mod/codecs/mod_isac/decode.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * decode_B.c
+ *
+ * This file contains definition of funtions for decoding.
+ * Decoding of lower-band, including normal-decoding and RCU decoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+
+#include "codec.h"
+#include "entropy_coding.h"
+#include "pitch_estimator.h"
+#include "bandwidth_estimator.h"
+#include "structs.h"
+#include "settings.h"
+
+#include
+#include
+#include
+
+
+/*
+ * function to decode the bitstream
+ * returns the total number of bytes in the stream
+ */
+int
+WebRtcIsac_DecodeLb(
+ float* signal_out,
+ ISACLBDecStruct* ISACdecLB_obj,
+ WebRtc_Word16* current_framesamples,
+ WebRtc_Word16 isRCUPayload)
+{
+ int k, model;
+ int len, err;
+ WebRtc_Word16 bandwidthInd;
+
+ float LP_dec_float[FRAMESAMPLES_HALF];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+
+ double lo_filt_coef[(ORDERLO+1)*SUBFRAMES];
+ double hi_filt_coef[(ORDERHI+1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+
+ double PitchLags[4];
+ double PitchGains[4];
+ double AvgPitchGain;
+ WebRtc_Word16 PitchGains_Q12[4];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ float gain;
+
+ int frame_nb; /* counter */
+ int frame_mode; /* 0 for 20ms and 30ms, 1 for 60ms */
+ int processed_samples;
+
+ (ISACdecLB_obj->bitstr_obj).W_upper = 0xFFFFFFFF;
+ (ISACdecLB_obj->bitstr_obj).streamval = 0;
+ (ISACdecLB_obj->bitstr_obj).stream_index = 0;
+
+ len = 0;
+
+ /* decode framelength and BW estimation - not used,
+ only for stream pointer*/
+ err = WebRtcIsac_DecodeFrameLen(&ISACdecLB_obj->bitstr_obj,
+ current_framesamples);
+ if (err < 0) { // error check
+ return err;
+ }
+
+ /* frame_mode: 0, or 1 */
+ frame_mode = *current_framesamples/MAX_FRAMESAMPLES;
+ /* processed_samples: either 320 (20ms) or 480 (30, 60 ms) */
+ processed_samples = *current_framesamples/(frame_mode+1);
+
+ err = WebRtcIsac_DecodeSendBW(&ISACdecLB_obj->bitstr_obj, &bandwidthInd);
+ if (err < 0) { // error check
+ return err;
+ }
+
+ /* one loop if it's one frame (20 or 30ms), 2 loops if 2 frames
+ bundled together (60ms) */
+ for (frame_nb = 0; frame_nb <= frame_mode; frame_nb++) {
+ /* decode & dequantize pitch parameters */
+ err = WebRtcIsac_DecodePitchGain(&(ISACdecLB_obj->bitstr_obj),
+ PitchGains_Q12);
+ if (err < 0) { // error check
+ return err;
+ }
+
+ err = WebRtcIsac_DecodePitchLag(&ISACdecLB_obj->bitstr_obj,
+ PitchGains_Q12, PitchLags);
+ if (err < 0) { // error check
+ return err;
+ }
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3])>>2;
+
+ /* decode & dequantize FiltCoef */
+ err = WebRtcIsac_DecodeLpc(&ISACdecLB_obj->bitstr_obj,
+ lo_filt_coef,hi_filt_coef, &model);
+ if (err < 0) { // error check
+ return err;
+ }
+ /* decode & dequantize spectrum */
+ len = WebRtcIsac_DecodeSpecLb(&ISACdecLB_obj->bitstr_obj,
+ real_f, imag_f, AvgPitchGain_Q12);
+ if (len < 0) { // error check
+ return len;
+ }
+
+ /* inverse transform */
+ WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw,
+ &ISACdecLB_obj->fftstr_obj);
+
+ /* convert PitchGains back to FLOAT for pitchfilter_post */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k])/4096;
+ }
+
+ if(isRCUPayload)
+ {
+ for (k = 0; k < 240; k++) {
+ LPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ HPw[k] *= RCU_TRANSCODING_SCALE_INVERSE;
+ }
+ }
+
+ /* inverse pitch filter */
+ WebRtcIsac_PitchfilterPost(LPw, LPw_pf,
+ &ISACdecLB_obj->pitchfiltstr_obj, PitchLags, PitchGains);
+ /* convert AvgPitchGain back to FLOAT for computation of gain */
+ AvgPitchGain = ((float)AvgPitchGain_Q12)/4096;
+ gain = 1.0f - 0.45f * (float)AvgPitchGain;
+
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* reduce gain to compensate for pitch enhancer */
+ LPw_pf[ k ] *= gain;
+ }
+
+ if(isRCUPayload)
+ {
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ /* compensation for transcoding gain changes*/
+ LPw_pf[k] *= RCU_TRANSCODING_SCALE;
+ HPw[k] *= RCU_TRANSCODING_SCALE;
+ }
+ }
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsac_NormLatticeFilterAr(ORDERLO,
+ ISACdecLB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateLoG,
+ LPw_pf, lo_filt_coef, LP_dec_float);
+ WebRtcIsac_NormLatticeFilterAr(ORDERHI,
+ ISACdecLB_obj->maskfiltstr_obj.PostStateHiF,
+ (ISACdecLB_obj->maskfiltstr_obj).PostStateHiG,
+ HPw, hi_filt_coef, HP_dec_float);
+
+ /* recombine the 2 bands */
+ WebRtcIsac_FilterAndCombineFloat( LP_dec_float, HP_dec_float,
+ signal_out + frame_nb * processed_samples,
+ &ISACdecLB_obj->postfiltbankstr_obj);
+ }
+
+ return len;
+}
+
+
+/*
+ * This decode function is called when the codec is operating in 16 kHz
+ * bandwidth to decode the upperband, i.e. 8-16 kHz.
+ *
+ * Contrary to lower-band, the upper-band (8-16 kHz) is not split in
+ * frequency, but split to 12 sub-frames, i.e. twice as lower-band.
+ */
+int
+WebRtcIsac_DecodeUb16(
+ float* signal_out,
+ ISACUBDecStruct* ISACdecUB_obj,
+ WebRtc_Word16 isRCUPayload)
+{
+ int len, err;
+
+ double halfFrameFirst[FRAMESAMPLES_HALF];
+ double halfFrameSecond[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER+1) * (SUBFRAMES<<1) +
+ (UB_LPC_ORDER+1)];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+
+ len = 0;
+
+ /* decode & dequantize FiltCoef */
+ memset(percepFilterParam, 0, sizeof(percepFilterParam));
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac16kHz);
+ if (err < 0) { // error check
+ return err;
+ }
+
+ /* decode & dequantize spectrum */
+ len = WebRtcIsac_DecodeSpecUB16(&ISACdecUB_obj->bitstr_obj, real_f,
+ imag_f);
+ if (len < 0) { // error check
+ return len;
+ }
+ if(isRCUPayload)
+ {
+ int n;
+ for(n = 0; n < 240; n++)
+ {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+
+ /* inverse transform */
+ WebRtcIsac_Spec2time(real_f, imag_f, halfFrameFirst, halfFrameSecond,
+ &ISACdecUB_obj->fftstr_obj);
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
+ ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameFirst,
+ &percepFilterParam[(UB_LPC_ORDER+1)], signal_out);
+
+ WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
+ ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, halfFrameSecond,
+ &percepFilterParam[(UB_LPC_ORDER + 1) * SUBFRAMES + (UB_LPC_ORDER+1)],
+ &signal_out[FRAMESAMPLES_HALF]);
+
+ return len;
+}
+
+/*
+ * This decode function is called when the codec operates at 0-12 kHz
+ * bandwidth to decode the upperband, i.e. 8-12 kHz.
+ *
+ * At the encoder the upper-band is split into two band, 8-12 kHz & 12-16
+ * kHz, and only 8-12 kHz is encoded. At the decoder, 8-12 kHz band is
+ * reconstructed and 12-16 kHz replaced with zeros. Then two bands
+ * are combined, to reconstruct the upperband 8-16 kHz.
+ */
+int
+WebRtcIsac_DecodeUb12(
+ float* signal_out,
+ ISACUBDecStruct* ISACdecUB_obj,
+ WebRtc_Word16 isRCUPayload)
+{
+ int len, err;
+
+ float LP_dec_float[FRAMESAMPLES_HALF];
+ float HP_dec_float[FRAMESAMPLES_HALF];
+
+ double LPw[FRAMESAMPLES_HALF];
+ double HPw[FRAMESAMPLES_HALF];
+
+ double percepFilterParam[(UB_LPC_ORDER+1)*SUBFRAMES];
+
+ double real_f[FRAMESAMPLES_HALF];
+ double imag_f[FRAMESAMPLES_HALF];
+
+ len = 0;
+
+ /* decode & dequantize FiltCoef */
+ err = WebRtcIsac_DecodeInterpolLpcUb(&ISACdecUB_obj->bitstr_obj,
+ percepFilterParam, isac12kHz);
+ if(err < 0) { // error check
+ return err;
+ }
+
+ /* decode & dequantize spectrum */
+ len = WebRtcIsac_DecodeSpecUB12(&ISACdecUB_obj->bitstr_obj,
+ real_f, imag_f);
+ if(len < 0) { // error check
+ return len;
+ }
+
+ if(isRCUPayload)
+ {
+ int n;
+ for(n = 0; n < 240; n++)
+ {
+ real_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ imag_f[n] *= RCU_TRANSCODING_SCALE_UB_INVERSE;
+ }
+ }
+
+ /* inverse transform */
+ WebRtcIsac_Spec2time(real_f, imag_f, LPw, HPw, &ISACdecUB_obj->fftstr_obj);
+
+ /* perceptual post-filtering (using normalized lattice filter) */
+ WebRtcIsac_NormLatticeFilterAr(UB_LPC_ORDER,
+ ISACdecUB_obj->maskfiltstr_obj.PostStateLoF,
+ (ISACdecUB_obj->maskfiltstr_obj).PostStateLoG, LPw,
+ percepFilterParam, LP_dec_float);
+
+ /* Zerro for upper-band */
+ memset(HP_dec_float, 0, sizeof(float) * (FRAMESAMPLES_HALF));
+
+ /* recombine the 2 bands */
+ WebRtcIsac_FilterAndCombineFloat(HP_dec_float, LP_dec_float, signal_out,
+ &ISACdecUB_obj->postfiltbankstr_obj);
+
+
+
+ return len;
+}
diff --git a/src/mod/codecs/mod_isac/decode_bwe.c b/src/mod/codecs/mod_isac/decode_bwe.c
new file mode 100644
index 0000000000..cdac7fa8bf
--- /dev/null
+++ b/src/mod/codecs/mod_isac/decode_bwe.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "structs.h"
+#include "bandwidth_estimator.h"
+#include "entropy_coding.h"
+#include "codec.h"
+
+
+int
+WebRtcIsac_EstimateBandwidth(
+ BwEstimatorstr* bwest_str,
+ Bitstr* streamdata,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts,
+ enum IsacSamplingRate encoderSampRate,
+ enum IsacSamplingRate decoderSampRate)
+{
+ WebRtc_Word16 index;
+ WebRtc_Word16 frame_samples;
+ WebRtc_UWord32 sendTimestampIn16kHz;
+ WebRtc_UWord32 arrivalTimestampIn16kHz;
+ WebRtc_UWord32 diffSendTime;
+ WebRtc_UWord32 diffArrivalTime;
+ int err;
+
+ /* decode framelength and BW estimation */
+ err = WebRtcIsac_DecodeFrameLen(streamdata, &frame_samples);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+ err = WebRtcIsac_DecodeSendBW(streamdata, &index);
+ if(err < 0) // error check
+ {
+ return err;
+ }
+
+ /* UPDATE ESTIMATES FROM OTHER SIDE */
+ err = WebRtcIsac_UpdateUplinkBwImpl(bwest_str, index, encoderSampRate);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ // We like BWE to work at 16 kHz sampling rate,
+ // therefore, we have to change the timestamps accordingly.
+ // translate the send timestamp if required
+ diffSendTime = (WebRtc_UWord32)((WebRtc_UWord32)send_ts -
+ (WebRtc_UWord32)bwest_str->senderTimestamp);
+ bwest_str->senderTimestamp = send_ts;
+
+ diffArrivalTime = (WebRtc_UWord32)((WebRtc_UWord32)arr_ts -
+ (WebRtc_UWord32)bwest_str->receiverTimestamp);
+ bwest_str->receiverTimestamp = arr_ts;
+
+ if(decoderSampRate == kIsacSuperWideband)
+ {
+ diffArrivalTime = (WebRtc_UWord32)diffArrivalTime >> 1;
+ diffSendTime = (WebRtc_UWord32)diffSendTime >> 1;
+ }
+ // arrival timestamp in 16 kHz
+ arrivalTimestampIn16kHz = (WebRtc_UWord32)((WebRtc_UWord32)
+ bwest_str->prev_rec_arr_ts + (WebRtc_UWord32)diffArrivalTime);
+ // send timestamp in 16 kHz
+ sendTimestampIn16kHz = (WebRtc_UWord32)((WebRtc_UWord32)
+ bwest_str->prev_rec_send_ts + (WebRtc_UWord32)diffSendTime);
+
+ err = WebRtcIsac_UpdateBandwidthEstimator(bwest_str, rtp_seq_number,
+ (frame_samples * 1000) / FS, sendTimestampIn16kHz,
+ arrivalTimestampIn16kHz, packet_size);
+ // error check
+ if(err < 0)
+ {
+ return err;
+ }
+
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/division_operations.c b/src/mod/codecs/mod_isac/division_operations.c
new file mode 100644
index 0000000000..b143373a2f
--- /dev/null
+++ b/src/mod/codecs/mod_isac/division_operations.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains implementations of the divisions
+ * WebRtcSpl_DivU32U16()
+ * WebRtcSpl_DivW32W16()
+ * WebRtcSpl_DivW32W16ResW16()
+ * WebRtcSpl_DivResultInQ31()
+ * WebRtcSpl_DivW32HiLow()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_UWord32)(num / den);
+ } else
+ {
+ return (WebRtc_UWord32)0xFFFFFFFF;
+ }
+}
+
+WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_Word32)(num / den);
+ } else
+ {
+ return (WebRtc_Word32)0x7FFFFFFF;
+ }
+}
+
+WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den)
+{
+ // Guard against division with 0
+ if (den != 0)
+ {
+ return (WebRtc_Word16)(num / den);
+ } else
+ {
+ return (WebRtc_Word16)0x7FFF;
+ }
+}
+
+WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den)
+{
+ WebRtc_Word32 L_num = num;
+ WebRtc_Word32 L_den = den;
+ WebRtc_Word32 div = 0;
+ int k = 31;
+ int change_sign = 0;
+
+ if (num == 0)
+ return 0;
+
+ if (num < 0)
+ {
+ change_sign++;
+ L_num = -num;
+ }
+ if (den < 0)
+ {
+ change_sign++;
+ L_den = -den;
+ }
+ while (k--)
+ {
+ div <<= 1;
+ L_num <<= 1;
+ if (L_num >= L_den)
+ {
+ L_num -= L_den;
+ div++;
+ }
+ }
+ if (change_sign == 1)
+ {
+ div = -div;
+ }
+ return div;
+}
+
+WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
+ WebRtc_Word16 den_low)
+{
+ WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low;
+ WebRtc_Word32 tmpW32;
+
+ approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi);
+ // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
+
+ // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
+ tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1)
+ + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1);
+ // tmpW32 = den * approx
+
+ tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
+
+ // Store tmpW32 in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // tmpW32 = 1/den in Q29
+ tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx)
+ >> 15)) << 1);
+
+ // 1/den in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Store num in hi and low format
+ num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16);
+ num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1);
+
+ // num * (1/den) by 32 bit multiplication (result in Q28)
+
+ tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low)
+ >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15));
+
+ // Put result in Q31 (convert from Q28)
+ tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
+
+ return tmpW32;
+}
diff --git a/src/mod/codecs/mod_isac/dot_product_with_scale.c b/src/mod/codecs/mod_isac/dot_product_with_scale.c
new file mode 100644
index 0000000000..6e085fdb60
--- /dev/null
+++ b/src/mod/codecs/mod_isac/dot_product_with_scale.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_DotProductWithScale().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16 *vector1, WebRtc_Word16 *vector2,
+ int length, int scaling)
+{
+ WebRtc_Word32 sum;
+ int i;
+#ifdef _ARM_OPT_
+#pragma message("NOTE: _ARM_OPT_ optimizations are used")
+ WebRtc_Word16 len4 = (length >> 2) << 2;
+#endif
+
+ sum = 0;
+
+#ifndef _ARM_OPT_
+ for (i = 0; i < length; i++)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1++, *vector2++, scaling);
+ }
+#else
+ if (scaling == 0)
+ {
+ for (i = 0; i < len4; i = i + 4)
+ {
+ sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
+ vector1++;
+ vector2++;
+ }
+
+ for (i = len4; i < length; i++)
+ {
+ sum += WEBRTC_SPL_MUL_16_16(*vector1, *vector2);
+ vector1++;
+ vector2++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < len4; i = i + 4)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
+ vector1++;
+ vector2++;
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
+ vector1++;
+ vector2++;
+ }
+
+ for (i = len4; i < length; i++)
+ {
+ sum += WEBRTC_SPL_MUL_16_16_RSFT(*vector1, *vector2, scaling);
+ vector1++;
+ vector2++;
+ }
+ }
+#endif
+
+ return sum;
+}
diff --git a/src/mod/codecs/mod_isac/downsample_fast.c b/src/mod/codecs/mod_isac/downsample_fast.c
new file mode 100644
index 0000000000..cce463c5d3
--- /dev/null
+++ b/src/mod/codecs/mod_isac/downsample_fast.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_DownsampleFast().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_DownsampleFast(WebRtc_Word16 *in_ptr, WebRtc_Word16 in_length,
+ WebRtc_Word16 *out_ptr, WebRtc_Word16 out_length,
+ WebRtc_Word16 *B, WebRtc_Word16 B_length, WebRtc_Word16 factor,
+ WebRtc_Word16 delay)
+{
+ WebRtc_Word32 o;
+ int i, j;
+
+ WebRtc_Word16 *downsampled_ptr = out_ptr;
+ WebRtc_Word16 *b_ptr;
+ WebRtc_Word16 *x_ptr;
+ WebRtc_Word16 endpos = delay
+ + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16(factor, (out_length - 1)) + 1;
+
+ if (in_length < endpos)
+ {
+ return -1;
+ }
+
+ for (i = delay; i < endpos; i += factor)
+ {
+ b_ptr = &B[0];
+ x_ptr = &in_ptr[i];
+
+ o = (WebRtc_Word32)2048; // Round val
+
+ for (j = 0; j < B_length; j++)
+ {
+ o += WEBRTC_SPL_MUL_16_16(*b_ptr++, *x_ptr--);
+ }
+
+ o = WEBRTC_SPL_RSHIFT_W32(o, 12);
+
+ // If output is higher than 32768, saturate it. Same with negative side
+
+ *downsampled_ptr++ = WebRtcSpl_SatW32ToW16(o);
+ }
+
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/encode.c b/src/mod/codecs/mod_isac/encode.c
new file mode 100644
index 0000000000..75cd726507
--- /dev/null
+++ b/src/mod/codecs/mod_isac/encode.c
@@ -0,0 +1,1451 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode.c
+ *
+ * This file contains definition of funtions for encoding.
+ * Decoding of upper-band, including 8-12 kHz, when the bandwidth is
+ * 0-12 kHz, and 8-16 kHz, when the bandwidth is 0-16 kHz.
+ *
+ */
+
+#include
+#include
+
+#include "structs.h"
+#include "codec.h"
+#include "pitch_estimator.h"
+#include "entropy_coding.h"
+#include "arith_routines.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "spectrum_ar_model_tables.h"
+#include "lpc_tables.h"
+#include "lpc_analysis.h"
+#include "bandwidth_estimator.h"
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+
+
+#define UB_LOOKAHEAD 24
+
+/*
+ Rate allocation tables of lower and upper-band bottleneck for
+ 12kHz & 16kHz bandwidth.
+
+ 12 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 38 kbps and 45 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 38,
+ 39.17, 40.33, 41.5, 42.67, 43.83 and 45. For every entery, the lower-band
+ and the upper-band bottlenecks are specified in
+ 'kLowerBandBitRate12' and 'kUpperBandBitRate12'
+ tables, respectively. E.g. the overall rate of 41.5 kbps corresponts to a
+ bottleneck of 31 kbps for lower-band and 27 kbps for upper-band. Given an
+ overall bottleneck of the codec, we use linear interpolation to get
+ lower-band and upper-band bottlenecks.
+
+ 16 kHz bandwidth
+ -----------------
+ The overall bottleneck of the coder is between 50 kbps and 56 kbps. We have
+ considered 7 enteries, uniformly distributed in this interval, i.e. 50, 51.2,
+ 52.4, 53.6, 54.8 and 56. For every entery, the lower-band and the upper-band
+ bottlenecks are specified in 'kLowerBandBitRate16' and
+ 'kUpperBandBitRate16' tables, respectively. E.g. the overall rate
+ of 53.6 kbps corresponts to a bottleneck of 32 kbps for lower-band and 30
+ kbps for upper-band. Given an overall bottleneck of the codec, we use linear
+ interpolation to get lower-band and upper-band bottlenecks.
+
+*/
+
+// 38 39.17 40.33 41.5 42.67 43.83 45
+static const WebRtc_Word16 kLowerBandBitRate12[7] = {
+ 29000, 30000, 30000, 31000, 31000, 32000, 32000};
+static const WebRtc_Word16 kUpperBandBitRate12[7] = {
+ 25000, 25000, 27000, 27000, 29000, 29000, 32000};
+
+// 50 51.2 52.4 53.6 54.8 56
+static const WebRtc_Word16 kLowerBandBitRate16[6] = {
+ 31000, 31000, 32000, 32000, 32000, 32000};
+static const WebRtc_Word16 kUpperBandBitRate16[6] = {
+ 28000, 29000, 29000, 30000, 31000, 32000};
+
+/******************************************************************************
+ * WebRtcIsac_RateAllocation()
+ * Internal function to perform a rate-allocation for upper and lower-band,
+ * given a total rate.
+ *
+ * Input:
+ * - inRateBitPerSec : a total bottleneck in bits/sec.
+ *
+ * Output:
+ * - rateLBBitPerSec : a bottleneck allocated to the lower-band
+ * in bits/sec.
+ * - rateUBBitPerSec : a bottleneck allocated to the upper-band
+ * in bits/sec.
+ *
+ * Return value : 0 if rate allocation has been successful.
+ * -1 if failed to allocate rates.
+ */
+
+WebRtc_Word16
+WebRtcIsac_RateAllocation(
+ WebRtc_Word32 inRateBitPerSec,
+ double* rateLBBitPerSec,
+ double* rateUBBitPerSec,
+ enum ISACBandwidth* bandwidthKHz)
+{
+ WebRtc_Word16 idx;
+ double idxD;
+ double idxErr;
+ if(inRateBitPerSec < 38000)
+ {
+ // If the given overall bottleneck is less than 38000 then
+ // then codec has to operate in wideband mode, i.e. 8 kHz
+ // bandwidth.
+ *rateLBBitPerSec = (WebRtc_Word16)((inRateBitPerSec > 32000)?
+ 32000:inRateBitPerSec);
+ *rateUBBitPerSec = 0;
+ *bandwidthKHz = isac8kHz;
+ }
+ else if((inRateBitPerSec >= 38000) && (inRateBitPerSec < 50000))
+ {
+ // At a bottleneck between 38 and 50 kbps the codec is operating
+ // at 12 kHz bandwidth. Using xxxBandBitRate12[] to calculates
+ // upper/lower bottleneck
+
+ // find the bottlenecks by linear interpolation
+ // step is (45000 - 38000)/6.0 we use the inverse of it.
+ const double stepSizeInv = 8.5714286e-4;
+ idxD = (inRateBitPerSec - 38000) * stepSizeInv;
+ idx = (idxD >= 6)? 6:((WebRtc_Word16)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate12[idx];
+ *rateUBBitPerSec = kUpperBandBitRate12[idx];
+
+ if(idx < 6)
+ {
+ *rateLBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kLowerBandBitRate12[idx + 1] -
+ kLowerBandBitRate12[idx]));
+ *rateUBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kUpperBandBitRate12[idx + 1] -
+ kUpperBandBitRate12[idx]));
+ }
+
+ *bandwidthKHz = isac12kHz;
+ }
+ else if((inRateBitPerSec >= 50000) && (inRateBitPerSec <= 56000))
+ {
+ // A bottleneck between 50 and 56 kbps corresponds to bandwidth
+ // of 16 kHz. Using xxxBandBitRate16[] to calculates
+ // upper/lower bottleneck
+
+ // find the bottlenecks by linear interpolation
+ // step is (56000 - 50000)/5 we use the inverse of it
+ const double stepSizeInv = 8.3333333e-4;
+ idxD = (inRateBitPerSec - 50000) * stepSizeInv;
+ idx = (idxD >= 5)? 5:((WebRtc_Word16)idxD);
+ idxErr = idxD - idx;
+ *rateLBBitPerSec = kLowerBandBitRate16[idx];
+ *rateUBBitPerSec = kUpperBandBitRate16[idx];
+
+ if(idx < 5)
+ {
+ *rateLBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kLowerBandBitRate16[idx + 1] -
+ kLowerBandBitRate16[idx]));
+
+ *rateUBBitPerSec += (WebRtc_Word16)(idxErr *
+ (kUpperBandBitRate16[idx + 1] -
+ kUpperBandBitRate16[idx]));
+ }
+
+ *bandwidthKHz = isac16kHz;
+ }
+ else
+ {
+ // Out-of-range botlteneck value.
+ return -1;
+ }
+
+ // limit the values.
+ *rateLBBitPerSec = (*rateLBBitPerSec > 32000)? 32000:*rateLBBitPerSec;
+ *rateUBBitPerSec = (*rateUBBitPerSec > 32000)? 32000:*rateUBBitPerSec;
+
+ return 0;
+}
+
+
+
+int
+WebRtcIsac_EncodeLb(
+ float* in,
+ ISACLBEncStruct* ISACencLB_obj,
+ WebRtc_Word16 codingMode,
+ WebRtc_Word16 bottleneckIndex)
+{
+ int stream_length = 0;
+ int err;
+ int k;
+ int iterCntr;
+
+ double lofilt_coef[(ORDERLO+1)*SUBFRAMES];
+ double hifilt_coef[(ORDERHI+1)*SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LP_lookahead_pf[FRAMESAMPLES_HALF + QLOOKAHEAD];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ double LPw_pf[FRAMESAMPLES_HALF];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ double PitchLags[4];
+ double PitchGains[4];
+ WebRtc_Word16 PitchGains_Q12[4];
+ WebRtc_Word16 AvgPitchGain_Q12;
+
+ int frame_mode; /* 0 for 30ms, 1 for 60ms */
+ int processed_samples, status = 0;
+
+ double bits_gains;
+ int bmodel;
+
+ transcode_obj transcodingParam;
+ double bytesLeftSpecCoding;
+ WebRtc_UWord16 payloadLimitBytes;
+
+ /* copy new frame length and bottle neck rate only for the first
+ 10 ms data */
+ if (ISACencLB_obj->buffer_index == 0) {
+ /* set the framelength for the next packet */
+ ISACencLB_obj->current_framesamples = ISACencLB_obj->new_framelength;
+ }
+ /* frame_mode is 0 (30 ms) or 1 (60 ms) */
+ frame_mode = ISACencLB_obj->current_framesamples/MAX_FRAMESAMPLES;
+ /* processed_samples: 480 (30, 60 ms) */
+ processed_samples = ISACencLB_obj->current_framesamples/(frame_mode+1);
+
+ /* buffer speech samples (by 10ms packet) until the framelength */
+ /* is reached (30 or 60 ms) */
+ /****************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ ISACencLB_obj->data_buffer_float[k + ISACencLB_obj->buffer_index] =
+ in[k];
+ }
+
+ /* if buffersize is not equal to current framesize then increase index
+ and return. We do no encoding untill we have enough audio. */
+ if (ISACencLB_obj->buffer_index + FRAMESAMPLES_10ms != processed_samples) {
+ ISACencLB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* if buffer reached the right size, reset index and continue with
+ encoding the frame */
+ ISACencLB_obj->buffer_index = 0;
+
+ /* end of buffer function */
+ /**************************/
+
+ /* encoding */
+ /************/
+
+ if (frame_mode == 0 || ISACencLB_obj->frame_nb == 0 ) {
+ // This is to avoid Linux warnings until we change 'int' to 'Word32'
+ // at all places.
+ int intVar;
+ /* reset bitstream */
+ ISACencLB_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACencLB_obj->bitstr_obj.streamval = 0;
+ ISACencLB_obj->bitstr_obj.stream_index = 0;
+
+ if((codingMode == 0) && (frame_mode == 0) &&
+ (ISACencLB_obj->enforceFrameSize == 0)) {
+ ISACencLB_obj->new_framelength =
+ WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
+ ISACencLB_obj->current_framesamples);
+ }
+
+ ISACencLB_obj->s2nr = WebRtcIsac_GetSnr(
+ ISACencLB_obj->bottleneck, ISACencLB_obj->current_framesamples);
+
+ /* encode frame length */
+ status = WebRtcIsac_EncodeFrameLen(
+ ISACencLB_obj->current_framesamples, &ISACencLB_obj->bitstr_obj);
+ if (status < 0) {
+ /* Wrong frame size */
+ return status;
+ }
+ /* Save framelength for multiple packets memory */
+ ISACencLB_obj->SaveEnc_obj.framelength =
+ ISACencLB_obj->current_framesamples;
+
+ /* To be used for Redundant Coding */
+ ISACencLB_obj->lastBWIdx = bottleneckIndex;
+ intVar = (int)bottleneckIndex;
+ WebRtcIsac_EncodeReceiveBw(&intVar, &ISACencLB_obj->bitstr_obj);
+ }
+
+ /* split signal in two bands */
+ WebRtcIsac_SplitAndFilterFloat(ISACencLB_obj->data_buffer_float, LP, HP,
+ LP_lookahead, HP_lookahead, &ISACencLB_obj->prefiltbankstr_obj );
+
+ /* estimate pitch parameters and pitch-filter lookahead signal */
+ WebRtcIsac_PitchAnalysis(LP_lookahead, LP_lookahead_pf,
+ &ISACencLB_obj->pitchanalysisstr_obj, PitchLags, PitchGains);
+
+ /* encode in FIX Q12 */
+
+ /* convert PitchGain to Fixed point */
+ for (k=0;kframe_nb == 0)
+ {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 0;
+ } else {
+ ISACencLB_obj->SaveEnc_obj.startIdx = 1;
+ }
+
+ /* quantize & encode pitch parameters */
+ WebRtcIsac_EncodePitchGain(PitchGains_Q12, &ISACencLB_obj->bitstr_obj,
+ &ISACencLB_obj->SaveEnc_obj);
+ WebRtcIsac_EncodePitchLag(PitchLags, PitchGains_Q12,
+ &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj);
+
+ AvgPitchGain_Q12 = (PitchGains_Q12[0] + PitchGains_Q12[1] +
+ PitchGains_Q12[2] + PitchGains_Q12[3])>>2;
+
+ /* find coefficients for perceptual pre-filters */
+ WebRtcIsac_GetLpcCoefLb(LP_lookahead_pf, HP_lookahead,
+ &ISACencLB_obj->maskfiltstr_obj, ISACencLB_obj->s2nr,
+ PitchGains_Q12, lofilt_coef, hifilt_coef);
+
+ /* code LPC model and shape - gains not quantized yet */
+ WebRtcIsac_EncodeLpcLb(lofilt_coef, hifilt_coef, &bmodel, &bits_gains,
+ &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj);
+
+ /* convert PitchGains back to FLOAT for pitchfilter_pre */
+ for (k = 0; k < 4; k++) {
+ PitchGains[k] = ((float)PitchGains_Q12[k])/4096;
+ }
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ transcodingParam.W_upper = ISACencLB_obj->bitstr_obj.W_upper;
+ transcodingParam.stream_index = ISACencLB_obj->bitstr_obj.stream_index;
+ transcodingParam.streamval = ISACencLB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] = ISACencLB_obj->bitstr_obj.stream[
+ ISACencLB_obj->bitstr_obj.stream_index - 2];
+ transcodingParam.stream[1] = ISACencLB_obj->bitstr_obj.stream[
+ ISACencLB_obj->bitstr_obj.stream_index - 1];
+ transcodingParam.stream[2] = ISACencLB_obj->bitstr_obj.stream[
+ ISACencLB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them */
+ for(k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lofilt_coef[(LPC_LOBAND_ORDER+1)*k];
+ transcodingParam.hiFiltGain[k] = hifilt_coef[(LPC_HIBAND_ORDER+1)*k];
+ }
+
+ /* Code gains */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef, bmodel,
+ &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj);
+
+ /* Get the correct value for the payload limit and calculate the
+ number of bytes left for coding the spectrum.*/
+ if((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* It is a 60ms and we are in the first 30ms then the limit at
+ this point should be half of the assigned value */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 >> 1;
+ }
+ else if (frame_mode == 0) {
+ /* It is a 30ms frame */
+ /* Subract 3 because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes30 - 3;
+ } else {
+ /* This is the second half of a 60ms frame. */
+ /* Subract 3 because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencLB_obj->payloadLimitBytes60 - 3;
+ }
+ bytesLeftSpecCoding = payloadLimitBytes - transcodingParam.stream_index;
+
+ /* perceptual pre-filtering (using normalized lattice filter) */
+ /* low-band filtering */
+ WebRtcIsac_NormLatticeFilterMa(ORDERLO,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateLoG, LP, lofilt_coef, LPw);
+ /* high-band filtering */
+ WebRtcIsac_NormLatticeFilterMa(ORDERHI,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiF,
+ ISACencLB_obj->maskfiltstr_obj.PreStateHiG, HP, hifilt_coef, HPw);
+
+
+ /* pitch filter */
+ WebRtcIsac_PitchfilterPre(LPw, LPw_pf, &ISACencLB_obj->pitchfiltstr_obj,
+ PitchLags, PitchGains);
+
+ /* transform */
+ WebRtcIsac_Time2Spec(LPw_pf, HPw, fre, fim, &ISACencLB_obj->fftstr_obj);
+
+
+ /* Save data for multiple packets memory */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ ISACencLB_obj->SaveEnc_obj.fre[k +
+ ISACencLB_obj->SaveEnc_obj.startIdx*FRAMESAMPLES_HALF] = fre[k];
+ ISACencLB_obj->SaveEnc_obj.fim[k +
+ ISACencLB_obj->SaveEnc_obj.startIdx*FRAMESAMPLES_HALF] = fim[k];
+ }
+ ISACencLB_obj->SaveEnc_obj.AvgPitchGain[
+ ISACencLB_obj->SaveEnc_obj.startIdx] = AvgPitchGain_Q12;
+
+ /* quantization and lossless coding */
+ err = WebRtcIsac_EncodeSpecLb(fre, fim, &ISACencLB_obj->bitstr_obj,
+ AvgPitchGain_Q12);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload) */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30ms of a 60ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr = 0;
+ while((ISACencLB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+
+ if(iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size */
+ if((frame_mode == 1) && (ISACencLB_obj->frame_nb == 0)) {
+ /* This was the first 30ms of a 60ms frame. Although
+ the payload is larger than it should be but we let
+ the second 30ms be encoded. Maybe together we
+ won't exceed the limit. */
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ } else if((frame_mode == 1) && (ISACencLB_obj->frame_nb == 1)) {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ if(err != -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ } else {
+ return status;
+ }
+ }
+
+ if(err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ // being coservative
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencLB_obj->bitstr_obj.stream_index -
+ transcodingParam.stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on
+ the number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr /
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains */
+ for (k = 0; k < SUBFRAMES; k++) {
+ lofilt_coef[(LPC_LOBAND_ORDER+1) * k] =
+ transcodingParam.loFiltGain[k] * transcodeScale;
+ hifilt_coef[(LPC_HIBAND_ORDER+1) * k] =
+ transcodingParam.hiFiltGain[k] * transcodeScale;
+ transcodingParam.loFiltGain[k] =
+ lofilt_coef[(LPC_LOBAND_ORDER+1) * k];
+ transcodingParam.hiFiltGain[k] =
+ hifilt_coef[(LPC_HIBAND_ORDER+1) * k];
+ }
+
+ /* Scale DFT coefficients */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (WebRtc_Word16)(fre[k] * transcodeScale);
+ fim[k] = (WebRtc_Word16)(fim[k] * transcodeScale);
+ }
+
+ /* Save data for multiple packets memory */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ ISACencLB_obj->SaveEnc_obj.fre[k +
+ ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF] =
+ fre[k];
+ ISACencLB_obj->SaveEnc_obj.fim[k +
+ ISACencLB_obj->SaveEnc_obj.startIdx * FRAMESAMPLES_HALF] =
+ fim[k];
+ }
+
+ /* Re-store the state of arithmetic coder before coding LPC gains */
+ ISACencLB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+ ISACencLB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+ ISACencLB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+ transcodingParam.stream[0];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+ transcodingParam.stream[1];
+ ISACencLB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+ transcodingParam.stream[2];
+
+ /* Code gains */
+ WebRtcIsac_EncodeLpcGainLb(lofilt_coef, hifilt_coef, bmodel,
+ &ISACencLB_obj->bitstr_obj, &ISACencLB_obj->SaveEnc_obj);
+
+ /* Update the number of bytes left for encoding the spectrum */
+ bytesLeftSpecCoding = payloadLimitBytes -
+ transcodingParam.stream_index;
+
+ /* Encode the spectrum */
+ err = WebRtcIsac_EncodeSpecLb(fre, fim, &ISACencLB_obj->bitstr_obj,
+ AvgPitchGain_Q12);
+ if((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload) */
+ if (frame_mode == 1 && ISACencLB_obj->frame_nb == 1) {
+ /* If this is the second 30ms of a 60ms frame reset
+ this such that in the next call encoder starts fresh. */
+ ISACencLB_obj->frame_nb = 0;
+ }
+ return err;
+ }
+ iterCntr++;
+ }
+
+ /* i.e. 60 ms framesize and just processed the first 30ms, */
+ /* go back to main function to buffer the other 30ms speech frame */
+ if (frame_mode == 1)
+ {
+ if(ISACencLB_obj->frame_nb == 0)
+ {
+ ISACencLB_obj->frame_nb = 1;
+ return 0;
+ }
+ else if(ISACencLB_obj->frame_nb == 1)
+ {
+ ISACencLB_obj->frame_nb = 0;
+ /* also update the framelength for next packet,
+ in Adaptive mode only */
+ if (codingMode == 0 && (ISACencLB_obj->enforceFrameSize == 0))
+ {
+ ISACencLB_obj->new_framelength =
+ WebRtcIsac_GetNewFrameLength(ISACencLB_obj->bottleneck,
+ ISACencLB_obj->current_framesamples);
+ }
+ }
+ }
+ else
+ {
+ ISACencLB_obj->frame_nb = 0;
+ }
+
+ /* complete arithmetic coding */
+ stream_length = WebRtcIsac_EncTerminate(&ISACencLB_obj->bitstr_obj);
+
+ return stream_length;
+}
+
+int
+WebRtcIsac_EncodeUb16(
+ float* in,
+ ISACUBEncStruct* ISACencUB_obj,
+ WebRtc_Word32 jitterInfo)
+{
+ int err;
+ int k;
+
+ double lpcVecs[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double percepFilterParams[(1 + UB_LPC_ORDER) * (SUBFRAMES<<1) +
+ (1 + UB_LPC_ORDER)];
+
+ double LP_lookahead[FRAMESAMPLES];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[2];
+ double corr[SUBFRAMES<<1][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES<<1];
+ transcode_obj transcodingParam;
+ double bytesLeftSpecCoding;
+ WebRtc_UWord16 payloadLimitBytes;
+ WebRtc_UWord16 iterCntr;
+ double s2nr;
+
+ /* buffer speech samples (by 10ms packet) until the framelength is */
+ /* reached (30 or 60 ms) */
+ /*********************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ for (k = 0; k < FRAMESAMPLES_10ms; k++) {
+ ISACencUB_obj->data_buffer_float[k + ISACencUB_obj->buffer_index] =
+ in[k];
+ }
+
+ /* if buffersize is not equal to current framesize, and end of file is
+ not reached yet, we don't do encoding unless we have the whole frame */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+
+ /* end of buffer function */
+ /**************************/
+
+ /* encoding */
+ /************/
+
+ /* reset bitstream */
+ ISACencUB_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACencUB_obj->bitstr_obj.streamval = 0;
+ ISACencUB_obj->bitstr_obj.stream_index = 0;
+
+ /* bandwidth estimation and coding */
+ /* To be used for Redundant Coding */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+
+ status = WebRtcIsac_EncodeBandwidth(isac16kHz,
+ &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck,
+ FRAMESAMPLES);
+
+ memcpy(lpcVecs, ISACencUB_obj->lastLPCVec, UB_LPC_ORDER * sizeof(double));
+
+ for (k = 0; k < FRAMESAMPLES; k++) {
+ LP_lookahead[k] = ISACencUB_obj->data_buffer_float[UB_LOOKAHEAD + k];
+ }
+
+ /* find coefficients for perceptual pre-filters */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ &lpcVecs[UB_LPC_ORDER], corr, varscale, isac16kHz);
+
+ memcpy(ISACencUB_obj->lastLPCVec,
+ &lpcVecs[(UB16_LPC_VEC_PER_FRAME - 1) * (UB_LPC_ORDER)],
+ sizeof(double) * UB_LPC_ORDER);
+
+ /* code LPC model and shape - gains not quantized yet */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac16kHz, &ISACencUB_obj->SaveEnc_obj);
+
+
+ // the first set of lpc parameters are from the last sub-frame of
+ // the previous frame. so we don't care about them
+ WebRtcIsac_GetLpcGain(s2nr, &percepFilterParams[UB_LPC_ORDER + 1],
+ (SUBFRAMES<<1), lpcGains, corr, varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+ transcodingParam.stream[0] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index - 2];
+ transcodingParam.stream[1] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index - 1];
+ transcodingParam.stream[2] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them */
+ for(k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ transcodingParam.hiFiltGain[k] = lpcGains[SUBFRAMES + k];
+ }
+
+ // Store the gains for multiple encoding
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, (SUBFRAMES << 1) * sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+ WebRtcIsac_EncodeLpcGainUb(&lpcGains[SUBFRAMES], &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+
+ /* Get the correct value for the payload limit and calculate the number of
+ bytes left for coding the spectrum. It is a 30ms frame
+ Subract 3 because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ for (k = 0; k < (SUBFRAMES<<1); k++) {
+ percepFilterParams[k*(UB_LPC_ORDER + 1) + (UB_LPC_ORDER + 1)] =
+ lpcGains[k];
+ }
+
+ /* perceptual pre-filtering (using normalized lattice filter) */
+ /* first half-frame filtering */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[0],
+ &percepFilterParams[UB_LPC_ORDER + 1],
+ &LP_lookahead[0]);
+
+ /* Second half-frame filtering */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES_HALF],
+ &percepFilterParams[(UB_LPC_ORDER + 1) + SUBFRAMES *
+ (UB_LPC_ORDER + 1)], &LP_lookahead[FRAMESAMPLES_HALF]);
+
+ WebRtcIsac_Time2Spec(&LP_lookahead[0], &LP_lookahead[FRAMESAMPLES_HALF],
+ fre, fim, &ISACencUB_obj->fftstr_obj);
+
+ //Store FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ memcpy(&ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ // Prepare the audio buffer for the next packet
+ // move the last 3 ms to the beginning of the buffer
+ memcpy(ISACencUB_obj->data_buffer_float,
+ &ISACencUB_obj->data_buffer_float[FRAMESAMPLES],
+ LB_TOTAL_DELAY_SAMPLES * sizeof(float));
+ // start writing with 3 ms delay to compensate for the delay
+ // of the lower-band.
+ ISACencUB_obj->buffer_index = LB_TOTAL_DELAY_SAMPLES;
+
+ // Save the bit-stream object at this point for FEC.
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* quantization and lossless coding */
+ err = WebRtcIsac_EncodeSpecUB16(fre, fim, &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ return err;
+ }
+
+ iterCntr = 0;
+ while((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size */
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+
+ if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ // being conservative
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
+ transcodingParam.stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on the
+ number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr/
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] *= transcodeScale;
+ transcodingParam.hiFiltGain[k] *= transcodeScale;
+ }
+
+ /* Scale DFT coefficients */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (WebRtc_Word16)(fre[k] * transcodeScale + 0.5);
+ fim[k] = (WebRtc_Word16)(fim[k] * transcodeScale + 0.5);
+ }
+
+ //Store FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ memcpy(&ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ ISACencUB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+
+ ISACencUB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+
+ ISACencUB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+ transcodingParam.stream[0];
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+ transcodingParam.stream[1];
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+ transcodingParam.stream[2];
+
+ // Store the gains for multiple encoding
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains,
+ (SUBFRAMES << 1) * sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(transcodingParam.loFiltGain,
+ &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+ WebRtcIsac_EncodeLpcGainUb(transcodingParam.hiFiltGain,
+ &ISACencUB_obj->bitstr_obj,
+ &ISACencUB_obj->SaveEnc_obj.lpcGainIndex[SUBFRAMES]);
+
+ /* Update the number of bytes left for encoding the spectrum */
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ // Save the bit-stream object at this point for FEC.
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Encode the spectrum */
+ err = WebRtcIsac_EncodeSpecUB16(fre, fim, &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload) */
+ return err;
+ }
+ iterCntr++;
+ }
+
+ /* complete arithmetic coding */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+int
+WebRtcIsac_EncodeUb12(
+ float* in,
+ ISACUBEncStruct* ISACencUB_obj,
+ WebRtc_Word32 jitterInfo)
+{
+ int err;
+ int k;
+ int iterCntr;
+
+ double lpcVecs[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+ double percepFilterParams[(1 + UB_LPC_ORDER) * SUBFRAMES];
+ float LP[FRAMESAMPLES_HALF];
+ float HP[FRAMESAMPLES_HALF];
+
+ double LP_lookahead[FRAMESAMPLES_HALF];
+ double HP_lookahead[FRAMESAMPLES_HALF];
+ double LPw[FRAMESAMPLES_HALF];
+
+ double HPw[FRAMESAMPLES_HALF];
+ WebRtc_Word16 fre[FRAMESAMPLES_HALF]; /* Q7 */
+ WebRtc_Word16 fim[FRAMESAMPLES_HALF]; /* Q7 */
+
+ int status = 0;
+
+ double varscale[1];
+
+ double corr[UB_LPC_GAIN_DIM][UB_LPC_ORDER + 1];
+ double lpcGains[SUBFRAMES];
+ transcode_obj transcodingParam;
+ double bytesLeftSpecCoding;
+ WebRtc_UWord16 payloadLimitBytes;
+ double s2nr;
+
+ /* buffer speech samples (by 10ms packet) until the framelength is */
+ /* reached (30 or 60 ms) */
+ /********************************************************************/
+
+ /* fill the buffer with 10ms input data */
+ for (k=0; kdata_buffer_float[k + ISACencUB_obj->buffer_index] =
+ in[k];
+ }
+
+ /* if buffer-size is not equal to current frame-size then increase the
+ index and return. We do the encoding when we have enough audio. */
+ if (ISACencUB_obj->buffer_index + FRAMESAMPLES_10ms < FRAMESAMPLES) {
+ ISACencUB_obj->buffer_index += FRAMESAMPLES_10ms;
+ return 0;
+ }
+ /* if buffer reached the right size, reset index and continue
+ with encoding the frame */
+ ISACencUB_obj->buffer_index = 0;
+
+ /* end of buffer function */
+ /**************************/
+
+ /* encoding */
+ /************/
+
+ /* reset bitstream */
+ ISACencUB_obj->bitstr_obj.W_upper = 0xFFFFFFFF;
+ ISACencUB_obj->bitstr_obj.streamval = 0;
+ ISACencUB_obj->bitstr_obj.stream_index = 0;
+
+ /* bandwidth estimation and coding */
+ /* To be used for Redundant Coding */
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, &ISACencUB_obj->bitstr_obj);
+
+ status = WebRtcIsac_EncodeBandwidth(isac12kHz,
+ &ISACencUB_obj->bitstr_obj);
+ if (status < 0) {
+ return status;
+ }
+
+
+ s2nr = WebRtcIsac_GetSnr(ISACencUB_obj->bottleneck,
+ FRAMESAMPLES);
+
+ /* split signal in two bands */
+ WebRtcIsac_SplitAndFilterFloat(ISACencUB_obj->data_buffer_float, HP, LP,
+ HP_lookahead, LP_lookahead, &ISACencUB_obj->prefiltbankstr_obj);
+
+ /* find coefficients for perceptual pre-filters */
+ WebRtcIsac_GetLpcCoefUb(LP_lookahead, &ISACencUB_obj->maskfiltstr_obj,
+ lpcVecs, corr, varscale, isac12kHz);
+
+ /* code LPC model and shape - gains not quantized yet */
+ WebRtcIsac_EncodeLpcUB(lpcVecs, &ISACencUB_obj->bitstr_obj,
+ percepFilterParams, isac12kHz, &ISACencUB_obj->SaveEnc_obj);
+
+ WebRtcIsac_GetLpcGain(s2nr, percepFilterParams, SUBFRAMES, lpcGains,
+ corr, varscale);
+
+ /* Store the state of arithmetic coder before coding LPC gains */
+ transcodingParam.W_upper = ISACencUB_obj->bitstr_obj.W_upper;
+
+ transcodingParam.stream_index = ISACencUB_obj->bitstr_obj.stream_index;
+
+ transcodingParam.streamval = ISACencUB_obj->bitstr_obj.streamval;
+
+ transcodingParam.stream[0] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index - 2];
+
+ transcodingParam.stream[1] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index - 1];
+
+ transcodingParam.stream[2] = ISACencUB_obj->bitstr_obj.stream[
+ ISACencUB_obj->bitstr_obj.stream_index];
+
+ /* Store LPC Gains before encoding them */
+ for(k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] = lpcGains[k];
+ }
+
+ // Store the gains for multiple encoding
+ memcpy(ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
+ sizeof(double));
+
+ WebRtcIsac_EncodeLpcGainUb(lpcGains, &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ for(k = 0; k < SUBFRAMES; k++) {
+ percepFilterParams[k*(UB_LPC_ORDER + 1)] = lpcGains[k];
+ }
+
+ /* perceptual pre-filtering (using normalized lattice filter) */
+ /* low-band filtering */
+ WebRtcIsac_NormLatticeFilterMa(UB_LPC_ORDER,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoF,
+ ISACencUB_obj->maskfiltstr_obj.PreStateLoG, LP, percepFilterParams,
+ LPw);
+
+ /* Get the correct value for the payload limit and calculate the number
+ of bytes left for coding the spectrum. It is a 30ms frame Subract 3
+ because termination process may add 3 bytes */
+ payloadLimitBytes = ISACencUB_obj->maxPayloadSizeBytes -
+ ISACencUB_obj->numBytesUsed - 3;
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ memset(HPw, 0, sizeof(double) * FRAMESAMPLES_HALF);
+
+ /* transform */
+ WebRtcIsac_Time2Spec(LPw, HPw, fre, fim, &ISACencUB_obj->fftstr_obj);
+
+ //Store real FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ //Store imaginary FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ // Save the bit-stream object at this point for FEC.
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* quantization and lossless coding */
+ err = WebRtcIsac_EncodeSpecUB12(fre, fim, &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large
+ payload (we can cure too large payload) */
+ return err;
+ }
+ iterCntr = 0;
+ while((ISACencUB_obj->bitstr_obj.stream_index > payloadLimitBytes) ||
+ (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ double bytesSpecCoderUsed;
+ double transcodeScale;
+
+ if (iterCntr >= MAX_PAYLOAD_LIMIT_ITERATION) {
+ /* We were not able to limit the payload size */
+ return -ISAC_PAYLOAD_LARGER_THAN_LIMIT;
+ }
+
+ if (err == -ISAC_DISALLOWED_BITSTREAM_LENGTH) {
+ bytesSpecCoderUsed = STREAM_SIZE_MAX;
+ // being coservative
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed * 0.5;
+ } else {
+ bytesSpecCoderUsed = ISACencUB_obj->bitstr_obj.stream_index -
+ transcodingParam.stream_index;
+ transcodeScale = bytesLeftSpecCoding / bytesSpecCoderUsed;
+ }
+
+ /* To be safe, we reduce the scale depending on the
+ number of iterations. */
+ transcodeScale *= (1.0 - (0.9 * (double)iterCntr/
+ (double)MAX_PAYLOAD_LIMIT_ITERATION));
+
+ /* Scale the LPC Gains */
+ for (k = 0; k < SUBFRAMES; k++) {
+ transcodingParam.loFiltGain[k] *= transcodeScale;
+ }
+
+ /* Scale DFT coefficients */
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ fre[k] = (WebRtc_Word16)(fre[k] * transcodeScale + 0.5);
+ fim[k] = (WebRtc_Word16)(fim[k] * transcodeScale + 0.5);
+ }
+
+ //Store real FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.realFFT, fre,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+ //Store imaginary FFT coefficients for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.imagFFT, fim,
+ FRAMESAMPLES_HALF * sizeof(WebRtc_Word16));
+
+
+ /* Re-store the state of arithmetic coder before coding LPC gains */
+ ISACencUB_obj->bitstr_obj.W_upper = transcodingParam.W_upper;
+
+ ISACencUB_obj->bitstr_obj.stream_index = transcodingParam.stream_index;
+
+ ISACencUB_obj->bitstr_obj.streamval = transcodingParam.streamval;
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index - 2] =
+ transcodingParam.stream[0];
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index - 1] =
+ transcodingParam.stream[1];
+
+ ISACencUB_obj->bitstr_obj.stream[transcodingParam.stream_index] =
+ transcodingParam.stream[2];
+
+ // Store the gains for multiple encoding
+ memcpy(&ISACencUB_obj->SaveEnc_obj.lpcGain, lpcGains, SUBFRAMES *
+ sizeof(double));
+
+ // encode LPC gain and store quantization indices. HAving quantization
+ // indices reduces transcoding complexity if 'scale factor' is 1.
+ WebRtcIsac_EncodeLpcGainUb(transcodingParam.loFiltGain,
+ &ISACencUB_obj->bitstr_obj,
+ ISACencUB_obj->SaveEnc_obj.lpcGainIndex);
+
+ // Save the bit-stream object at this point for FEC.
+ memcpy(&ISACencUB_obj->SaveEnc_obj.bitStreamObj,
+ &ISACencUB_obj->bitstr_obj, sizeof(Bitstr));
+
+ /* Update the number of bytes left for encoding the spectrum */
+ bytesLeftSpecCoding = payloadLimitBytes -
+ ISACencUB_obj->bitstr_obj.stream_index;
+
+ /* Encode the spectrum */
+ err = WebRtcIsac_EncodeSpecUB12(fre, fim,
+ &ISACencUB_obj->bitstr_obj);
+ if ((err < 0) && (err != -ISAC_DISALLOWED_BITSTREAM_LENGTH)) {
+ /* There has been an error but it was not too large payload
+ (we can cure too large payload) */
+ return err;
+ }
+ iterCntr++;
+ }
+
+ /* complete arithmetic coding */
+ return WebRtcIsac_EncTerminate(&ISACencUB_obj->bitstr_obj);
+}
+
+
+
+
+
+
+/* This function is used to create a new bitstream with new BWE.
+ The same data as previously encoded with the function WebRtcIsac_Encoder().
+ The data needed is taken from the struct, where it was stored
+ when calling the encoder. */
+
+int WebRtcIsac_EncodeStoredDataLb(
+ const ISAC_SaveEncData_t* ISACSavedEnc_obj,
+ Bitstr* ISACBitStr_obj,
+ int BWnumber,
+ float scale)
+{
+ int ii;
+ int status;
+ int BWno = BWnumber;
+
+ const WebRtc_UWord16 *WebRtcIsac_kQPitchGainCdf_ptr[1];
+ const WebRtc_UWord16 **cdf;
+
+ double tmpLPCcoeffs_lo[(ORDERLO+1)*SUBFRAMES*2];
+ double tmpLPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*2];
+ int tmpLPCindex_g[12*2];
+ WebRtc_Word16 tmp_fre[FRAMESAMPLES], tmp_fim[FRAMESAMPLES];
+
+ /* Sanity Check - possible values for BWnumber is 0 - 23 */
+ if ((BWnumber < 0) || (BWnumber > 23)) {
+ return -ISAC_RANGE_ERROR_BW_ESTIMATOR;
+ }
+
+ /* reset bitstream */
+ ISACBitStr_obj->W_upper = 0xFFFFFFFF;
+ ISACBitStr_obj->streamval = 0;
+ ISACBitStr_obj->stream_index = 0;
+
+ /* encode frame length */
+ status = WebRtcIsac_EncodeFrameLen(ISACSavedEnc_obj->framelength,
+ ISACBitStr_obj);
+ if (status < 0) {
+ /* Wrong frame size */
+ return status;
+ }
+
+ /* Transcoding */
+ if ((scale > 0.0) && (scale < 1.0)) {
+ /* Compensate LPC gain */
+ for (ii = 0;
+ ii < ((ORDERLO + 1)* SUBFRAMES * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_lo[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_lo[ii];
+ }
+ for (ii = 0;
+ ii < ((ORDERHI + 1) * SUBFRAMES *(1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCcoeffs_hi[ii] = scale * ISACSavedEnc_obj->LPCcoeffs_hi[ii];
+ }
+ /* Scale DFT */
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = (WebRtc_Word16)((scale) *
+ (float)ISACSavedEnc_obj->fre[ii]) ;
+ tmp_fim[ii] = (WebRtc_Word16)((scale) *
+ (float)ISACSavedEnc_obj->fim[ii]) ;
+ }
+ } else {
+ for (ii = 0;
+ ii < (KLT_ORDER_GAIN * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmpLPCindex_g[ii] = ISACSavedEnc_obj->LPCindex_g[ii];
+ }
+ for (ii = 0;
+ ii < (FRAMESAMPLES_HALF * (1 + ISACSavedEnc_obj->startIdx));
+ ii++) {
+ tmp_fre[ii] = ISACSavedEnc_obj->fre[ii];
+ tmp_fim[ii] = ISACSavedEnc_obj->fim[ii];
+ }
+ }
+
+ /* encode bandwidth estimate */
+ WebRtcIsac_EncodeReceiveBw(&BWno, ISACBitStr_obj);
+
+ /* Loop over number of 30 msec */
+ for (ii = 0; ii <= ISACSavedEnc_obj->startIdx; ii++) {
+ /* encode pitch gains */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchGain_index[ii], WebRtcIsac_kQPitchGainCdf_ptr, 1);
+
+ /* entropy coding of quantization pitch lags */
+ /* voicing classificiation */
+ if (ISACSavedEnc_obj->meanGain[ii] < 0.2) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ } else if (ISACSavedEnc_obj->meanGain[ii] < 0.4) {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ } else {
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ }
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->pitchIndex[PITCH_SUBFRAMES*ii], cdf,
+ PITCH_SUBFRAMES);
+
+ /* LPC */
+ /* entropy coding of model number */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->LPCmodel[ii], WebRtcIsac_kQKltModelCdfPtr, 1);
+
+ /* entropy coding of quantization indices - LPC shape only */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &ISACSavedEnc_obj->LPCindex_s[KLT_ORDER_SHAPE*ii],
+ WebRtcIsac_kQKltCdfPtrShape[ISACSavedEnc_obj->LPCmodel[ii]],
+ KLT_ORDER_SHAPE);
+
+ /* If transcoding, get new LPC gain indices */
+ if (scale < 1.0) {
+ WebRtcIsac_TranscodeLPCCoef(&tmpLPCcoeffs_lo[(ORDERLO+1) *
+ SUBFRAMES*ii], &tmpLPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*ii],
+ ISACSavedEnc_obj->LPCmodel[ii],
+ &tmpLPCindex_g[KLT_ORDER_GAIN * ii]);
+ }
+
+ /* entropy coding of quantization indices - LPC gain */
+ WebRtcIsac_EncHistMulti(ISACBitStr_obj,
+ &tmpLPCindex_g[KLT_ORDER_GAIN*ii], WebRtcIsac_kQKltCdfPtrGain[
+ ISACSavedEnc_obj->LPCmodel[ii]], KLT_ORDER_GAIN);
+
+ /* quantization and lossless coding */
+ status = WebRtcIsac_EncodeSpecLb(&tmp_fre[ii*FRAMESAMPLES_HALF],
+ &tmp_fim[ii*FRAMESAMPLES_HALF], ISACBitStr_obj,
+ ISACSavedEnc_obj->AvgPitchGain[ii]);
+ if (status < 0) {
+ return status;
+ }
+ }
+
+ /* complete arithmetic coding */
+ return WebRtcIsac_EncTerminate(ISACBitStr_obj);
+}
+
+
+
+
+int WebRtcIsac_EncodeStoredDataUb12(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo,
+ float scale)
+{
+ int n;
+ int err;
+ double lpcGain[SUBFRAMES];
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+
+ /* reset bitstream */
+ bitStream->W_upper = 0xFFFFFFFF;
+ bitStream->streamval = 0;
+ bitStream->stream_index = 0;
+
+ // Encode jitter index
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
+
+ err = WebRtcIsac_EncodeBandwidth(isac12kHz, bitStream);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ // Encode LPC-shape
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
+ WebRtcIsac_kLpcShapeCdfMatUb12, UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+
+
+ // we only consider scales between zero and one.
+ if((scale <= 0.0) || (scale > 1.0))
+ {
+ scale = 1.0f;
+ }
+
+ if(scale == 1.0f)
+ {
+ //memcpy(lpcGain, ISACSavedEnc_obj->lpcGain, SUBFRAMES * sizeof(double));
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ // store FFT coefficients
+ err = WebRtcIsac_EncodeSpecUB12(ISACSavedEnc_obj->realFFT,
+ ISACSavedEnc_obj->imagFFT, bitStream);
+ }
+ else
+ {
+ /* scale lpc gain and FFT coefficients */
+ for(n = 0; n < SUBFRAMES; n++)
+ {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
+ }
+ // store lpc gain
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+ for(n = 0; n < FRAMESAMPLES_HALF; n++)
+ {
+ realFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->realFFT[n] + 0.5f);
+ imagFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->imagFFT[n] + 0.5f);
+ }
+ // store FFT coefficients
+ err = WebRtcIsac_EncodeSpecUB12(realFFT, imagFFT, bitStream);
+ }
+ if(err < 0)
+ {
+ // error happened while encoding FFT coefficients.
+ return err;
+ }
+
+ /* complete arithmetic coding */
+ return WebRtcIsac_EncTerminate(bitStream);
+}
+
+
+int
+WebRtcIsac_EncodeStoredDataUb16(
+ const ISACUBSaveEncDataStruct* ISACSavedEnc_obj,
+ Bitstr* bitStream,
+ WebRtc_Word32 jitterInfo,
+ float scale)
+{
+ int n;
+ int err;
+ double lpcGain[SUBFRAMES << 1];
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+
+ /* reset bitstream */
+ bitStream->W_upper = 0xFFFFFFFF;
+ bitStream->streamval = 0;
+ bitStream->stream_index = 0;
+
+ // Encode jitter index
+ WebRtcIsac_EncodeJitterInfo(jitterInfo, bitStream);
+
+ err = WebRtcIsac_EncodeBandwidth(isac16kHz, bitStream);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->indexLPCShape,
+ WebRtcIsac_kLpcShapeCdfMatUb16, UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+
+ // we only consider scales between zero and one.
+ if((scale <= 0.0) || (scale > 1.0))
+ {
+ scale = 1.0f;
+ }
+
+ if(scale == 1.0f)
+ {
+ // store gains
+ WebRtcIsac_EncHistMulti(bitStream, ISACSavedEnc_obj->lpcGainIndex,
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ WebRtcIsac_EncHistMulti(bitStream, &ISACSavedEnc_obj->lpcGainIndex[SUBFRAMES],
+ WebRtcIsac_kLpcGainCdfMat, UB_LPC_GAIN_DIM);
+ // store FFT coefficients
+ err = WebRtcIsac_EncodeSpecUB16(ISACSavedEnc_obj->realFFT,
+ ISACSavedEnc_obj->imagFFT, bitStream);
+
+ }
+ else
+ {
+ /* Scale Gain */
+ for(n = 0; n < SUBFRAMES; n++)
+ {
+ lpcGain[n] = scale * ISACSavedEnc_obj->lpcGain[n];
+ lpcGain[n + SUBFRAMES] = scale * ISACSavedEnc_obj->lpcGain[n + SUBFRAMES];
+ }
+ // store lpc gain
+ WebRtcIsac_StoreLpcGainUb(lpcGain, bitStream);
+ WebRtcIsac_StoreLpcGainUb(&lpcGain[SUBFRAMES], bitStream);
+ /* scale FFT coefficients */
+ for(n = 0; n < FRAMESAMPLES_HALF; n++)
+ {
+ realFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->realFFT[n] + 0.5f);
+ imagFFT[n] = (WebRtc_Word16)(scale * (float)ISACSavedEnc_obj->imagFFT[n] + 0.5f);
+ }
+ // store FFT coefficients
+ err = WebRtcIsac_EncodeSpecUB16(realFFT, imagFFT, bitStream);
+ }
+
+ if(err < 0)
+ {
+ // error happened while encoding FFT coefficients.
+ return err;
+ }
+
+ /* complete arithmetic coding */
+ return WebRtcIsac_EncTerminate(bitStream);
+}
+
+
+WebRtc_Word16
+WebRtcIsac_GetRedPayloadUb(
+ const ISACUBSaveEncDataStruct* ISACSavedEncObj,
+ Bitstr* bitStreamObj,
+ enum ISACBandwidth bandwidth)
+{
+ int n;
+ WebRtc_Word16 status;
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+
+ // store bit-stream object.
+ memcpy(bitStreamObj, &ISACSavedEncObj->bitStreamObj, sizeof(Bitstr));
+
+ // Scale FFT coefficients.
+ for(n = 0; n < FRAMESAMPLES_HALF; n++)
+ {
+ realFFT[n] = (WebRtc_Word16)((float)ISACSavedEncObj->realFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ imagFFT[n] = (WebRtc_Word16)((float)ISACSavedEncObj->imagFFT[n] *
+ RCU_TRANSCODING_SCALE_UB + 0.5);
+ }
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ status = WebRtcIsac_EncodeSpecUB12(realFFT, imagFFT, bitStreamObj);
+ break;
+ }
+ case isac16kHz:
+ {
+ status = WebRtcIsac_EncodeSpecUB16(realFFT, imagFFT, bitStreamObj);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(status < 0)
+ {
+ // error happened
+ return status;
+ }
+ else
+ {
+ // terminate entropy coding
+ return WebRtcIsac_EncTerminate(bitStreamObj);
+ }
+}
diff --git a/src/mod/codecs/mod_isac/encode_lpc_swb.c b/src/mod/codecs/mod_isac/encode_lpc_swb.c
new file mode 100644
index 0000000000..2bf4c36460
--- /dev/null
+++ b/src/mod/codecs/mod_isac/encode_lpc_swb.c
@@ -0,0 +1,708 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * code_LPC_UB.c
+ *
+ * This file contains definition of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#include "encode_lpc_swb.h"
+#include "typedefs.h"
+#include "settings.h"
+
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+
+#include
+#include
+#include
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+WebRtc_Word16
+WebRtcIsac_RemoveLarMean(
+ double* lar,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 numVec;
+ const double* meanLAR;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ // REMOVE MEAN
+ *lar++ -= meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16
+WebRtcIsac_DecorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ const double* ptrData;
+ const double* ptrRow;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 larVecCntr;
+ WebRtc_Word16 numVec;
+ const double* decorrMat;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ numVec = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // decorrMat * data
+ //
+ // data is assumed to contain 'numVec' of LAR
+ // vectors (mean removed) each of dimension 'UB_LPC_ORDER'
+ // concatenated one after the other.
+ //
+
+ ptrData = data;
+ for(larVecCntr = 0; larVecCntr < numVec; larVecCntr++)
+ {
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ ptrRow = &decorrMat[rowCntr * UB_LPC_ORDER];
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out += ptrData[colCntr] * ptrRow[colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16
+WebRtcIsac_DecorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ const double* decorrMat;
+ WebRtc_Word16 interVecDim;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ decorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // data * decorrMat
+ //
+ // data is of size 'interVecDim' * 'UB_LPC_ORDER'
+ // That is 'interVecDim' of LAR vectors (mean removed)
+ // in columns each of dimension 'UB_LPC_ORDER'.
+ // matrix is stored column-wise.
+ //
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] = 0;
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + colCntr * UB_LPC_ORDER] +=
+ data[coeffCntr + rowCntr * UB_LPC_ORDER] *
+ decorrMat[rowCntr * interVecDim + colCntr];
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double
+WebRtcIsac_QuantizeUncorrLar(
+ double* data,
+ int* recIdx,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 cntr;
+ WebRtc_Word32 idx;
+ WebRtc_Word16 interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+ const WebRtc_Word16* numQuantCell;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ numQuantCell = WebRtcIsac_kLpcShapeNumRecPointUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Quantize the parametrs.
+ //
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ idx = (WebRtc_Word32)floor((*data - leftRecPoint[cntr]) /
+ quantizationStepSize + 0.5);
+ if(idx < 0)
+ {
+ idx = 0;
+ }
+ else if(idx >= numQuantCell[cntr])
+ {
+ idx = numQuantCell[cntr] - 1;
+ }
+
+ *data++ = leftRecPoint[cntr] + idx * quantizationStepSize;
+ *recIdx++ = idx;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+WebRtc_Word16
+WebRtcIsac_DequantizeLpcParam(
+ const int* idx,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 cntr;
+ WebRtc_Word16 interVecDim;
+ const double* leftRecPoint;
+ double quantizationStepSize;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb12;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb12;
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ break;
+ }
+ case isac16kHz:
+ {
+ leftRecPoint = WebRtcIsac_kLpcShapeLeftRecPointUb16;
+ quantizationStepSize = WebRtcIsac_kLpcShapeQStepSizeUb16;
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ //
+ // Dequantize given the quantization indices
+ //
+
+ for(cntr = 0; cntr < UB_LPC_ORDER * interVecDim; cntr++)
+ {
+ *out++ = leftRecPoint[cntr] + *idx++ * quantizationStepSize;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16
+WebRtcIsac_CorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 numVec;
+ const double* ptrData;
+ const double* intraVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIntraVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ intraVecDecorrMat = &WebRtcIsac_kIintraVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+
+ ptrData = data;
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(colCntr = 0; colCntr < UB_LPC_ORDER; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_ORDER; rowCntr++)
+ {
+ *out += ptrData[rowCntr] *
+ intraVecDecorrMat[rowCntr * UB_LPC_ORDER + colCntr];
+ }
+ out++;
+ }
+ ptrData += UB_LPC_ORDER;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16
+WebRtcIsac_CorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+ WebRtc_Word16 interVecDim;
+ double myVec[UB16_LPC_VEC_PER_FRAME];
+ const double* interVecDecorrMat;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ interVecDim = UB_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb12[0][0];
+ break;
+ }
+ case isac16kHz:
+ {
+ interVecDim = UB16_LPC_VEC_PER_FRAME;
+ interVecDecorrMat = &WebRtcIsac_kInterVecDecorrMatUb16[0][0];
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ myVec[rowCntr] = 0;
+ for(colCntr = 0; colCntr < interVecDim; colCntr++)
+ {
+ myVec[rowCntr] += data[coeffCntr + colCntr * UB_LPC_ORDER] * //*ptrData *
+ interVecDecorrMat[rowCntr * interVecDim + colCntr];
+ //ptrData += UB_LPC_ORDER;
+ }
+ }
+
+ for(rowCntr = 0; rowCntr < interVecDim; rowCntr++)
+ {
+ out[coeffCntr + rowCntr * UB_LPC_ORDER] = myVec[rowCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+WebRtc_Word16
+WebRtcIsac_AddLarMean(
+ double* data,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 coeffCntr;
+ WebRtc_Word16 vecCntr;
+ WebRtc_Word16 numVec;
+ const double* meanLAR;
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ numVec = UB_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb12;
+ break;
+ }
+ case isac16kHz:
+ {
+ numVec = UB16_LPC_VEC_PER_FRAME;
+ meanLAR = WebRtcIsac_kMeanLarUb16;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ for(vecCntr = 0; vecCntr < numVec; vecCntr++)
+ {
+ for(coeffCntr = 0; coeffCntr < UB_LPC_ORDER; coeffCntr++)
+ {
+ *data++ += meanLAR[coeffCntr];
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+WebRtc_Word16
+WebRtcIsac_ToLogDomainRemoveMean(
+ double* data)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ data[coeffCntr] = log(data[coeffCntr]) - WebRtcIsac_kMeanLpcGain;
+ }
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateLPGain(
+ const double* data,
+ double* out)
+{
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out = 0;
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out += data[rowCntr] * WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr];
+ }
+ out++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+ double* data,
+ int* idx)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *idx = (int)floor((*data - WebRtcIsac_kLeftRecPointLpcGain[coeffCntr]) /
+ WebRtcIsac_kQSizeLpcGain + 0.5);
+
+ if(*idx < 0)
+ {
+ *idx = 0;
+ }
+ else if(*idx >= WebRtcIsac_kNumQCellLpcGain[coeffCntr])
+ {
+ *idx = WebRtcIsac_kNumQCellLpcGain[coeffCntr] - 1;
+ }
+ *data = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+
+ data++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcGain(
+ const int* idx,
+ double* out)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ *out = WebRtcIsac_kLeftRecPointLpcGain[coeffCntr] + *idx *
+ WebRtcIsac_kQSizeLpcGain;
+ out++;
+ idx++;
+ }
+ return 0;
+}
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateLpcGain(
+ const double* data,
+ double* out)
+{
+ WebRtc_Word16 rowCntr;
+ WebRtc_Word16 colCntr;
+
+ for(rowCntr = 0; rowCntr < UB_LPC_GAIN_DIM; rowCntr++)
+ {
+ *out = 0;
+ for(colCntr = 0; colCntr < UB_LPC_GAIN_DIM; colCntr++)
+ {
+ *out += WebRtcIsac_kLpcGainDecorrMat[rowCntr][colCntr] * data[colCntr];
+ }
+ out++;
+ }
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+WebRtc_Word16 WebRtcIsac_AddMeanToLinearDomain(
+ double* lpcGains)
+{
+ WebRtc_Word16 coeffCntr;
+ for(coeffCntr = 0; coeffCntr < UB_LPC_GAIN_DIM; coeffCntr++)
+ {
+ lpcGains[coeffCntr] = exp(lpcGains[coeffCntr] + WebRtcIsac_kMeanLpcGain);
+ }
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/encode_lpc_swb.h b/src/mod/codecs/mod_isac/encode_lpc_swb.h
new file mode 100644
index 0000000000..e7f1a76af2
--- /dev/null
+++ b/src/mod/codecs/mod_isac/encode_lpc_swb.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * encode_lpc_swb.h
+ *
+ * This file contains declaration of functions used to
+ * encode LPC parameters (Shape & gain) of the upper band.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
+
+#include "typedefs.h"
+#include "settings.h"
+#include "structs.h"
+
+
+/******************************************************************************
+ * WebRtcIsac_RemoveLarMean()
+ *
+ * Remove the means from LAR coefficients.
+ *
+ * Input:
+ * -lar : pointer to lar vectors. LAR vectors are
+ * concatenated.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -lar : pointer to mean-removed LAR:s.
+ *
+ *
+ */
+WebRtc_Word16 WebRtcIsac_RemoveLarMean(
+ double* lar,
+ WebRtc_Word16 bandwidth);
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateIntraVec()
+ *
+ * Remove the correlation amonge the components of LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from left.
+ *
+ * Input:
+ * -inLar : pointer to mean-removed LAR vecrtors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateIntraVec(
+ const double* inLAR,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateInterVec()
+ *
+ * Remover the correlation among mean-removed LAR vectors. If LAR vectors
+ * of one frame are put in a matrix where each column is a LAR vector of a
+ * sub-frame, then this is equivalent to multiplying the LAR matrix with
+ * a decorrelting mtrix from right.
+ *
+ * Input:
+ * -data : pointer to matrix of LAR vectors. The matrix
+ * is stored column-wise.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : decorrelated LAR vectors.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeUncorrLar()
+ *
+ * Quantize the uncorrelated parameters.
+ *
+ * Input:
+ * -data : uncorrelated LAR vectors.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : quantized version of the input.
+ * -idx : pointer to quantization indices.
+ */
+double WebRtcIsac_QuantizeUncorrLar(
+ double* data,
+ int* idx,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateIntraVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateIntraVec().
+ *
+ * Input:
+ * -data : uncorrelated parameters.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateIntraVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateInterVec()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateInterVec().
+ *
+ * Input:
+ * -data
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : correlated parametrs.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateInterVec(
+ const double* data,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_AddLarMean()
+ *
+ * This is the inverse of WebRtcIsac_RemoveLarMean()
+ *
+ * Input:
+ * -data : pointer to mean-removed LAR:s.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -data : pointer to LARs.
+ */
+WebRtc_Word16 WebRtcIsac_AddLarMean(
+ double* data,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcParam()
+ *
+ * Get the quantized value of uncorrelated LARs given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantiztion indices.
+ * -bandwidth : indicates if the given LAR vectors belong
+ * to SWB-12kHz or SWB-16kHz.
+ *
+ * Output:
+ * -out : pointer to quantized values.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcParam(
+ const int* idx,
+ double* out,
+ WebRtc_Word16 bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_ToLogDomainRemoveMean()
+ *
+ * Transform the LPC gain to log domain then remove the mean value.
+ *
+ * Input:
+ * -lpcGain : pointer to LPC Gain, expecting 6 LPC gains
+ *
+ * Output:
+ * -lpcGain : mean-removed in log domain.
+ */
+WebRtc_Word16 WebRtcIsac_ToLogDomainRemoveMean(
+ double* lpGains);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecorrelateLPGain()
+ *
+ * Decorrelate LPC gains. There are 6 LPC Gains per frame. This is like
+ * multiplying gain vector with decorrelating matrix.
+ *
+ * Input:
+ * -data : LPC gain in log-domain with mean removed.
+ *
+ * Output:
+ * -out : decorrelated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_DecorrelateLPGain(
+ const double* data,
+ double* out);
+
+
+/******************************************************************************
+ * WebRtcIsac_QuantizeLpcGain()
+ *
+ * Quantize the decorrelated log-domain gains.
+ *
+ * Input:
+ * -lpcGain : uncorrelated LPC gains.
+ *
+ * Output:
+ * -idx : quantization indices
+ * -lpcGain : quantized value of the inpt.
+ */
+double WebRtcIsac_QuantizeLpcGain(
+ double* lpGains,
+ int* idx);
+
+
+/******************************************************************************
+ * WebRtcIsac_DequantizeLpcGain()
+ *
+ * Get the quantized values given the quantization indices.
+ *
+ * Input:
+ * -idx : pointer to quantization indices.
+ *
+ * Output:
+ * -lpcGains : quantized values of the given parametes.
+ */
+WebRtc_Word16 WebRtcIsac_DequantizeLpcGain(
+ const int* idx,
+ double* lpGains);
+
+
+/******************************************************************************
+ * WebRtcIsac_CorrelateLpcGain()
+ *
+ * This is the inverse of WebRtcIsac_DecorrelateLPGain().
+ *
+ * Input:
+ * -data : decorrelated parameters.
+ *
+ * Output:
+ * -out : correlated parameters.
+ */
+WebRtc_Word16 WebRtcIsac_CorrelateLpcGain(
+ const double* data,
+ double* out);
+
+
+/******************************************************************************
+ * WebRtcIsac_AddMeanToLinearDomain()
+ *
+ * This is the inverse of WebRtcIsac_ToLogDomainRemoveMean().
+ *
+ * Input:
+ * -lpcGain : LPC gain in log-domain & mean removed
+ *
+ * Output:
+ * -lpcGain : LPC gain in normal domain.
+ */
+WebRtc_Word16 WebRtcIsac_AddMeanToLinearDomain(
+ double* lpcGains);
+
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENCODE_LPC_SWB_H_
diff --git a/src/mod/codecs/mod_isac/energy.c b/src/mod/codecs/mod_isac/energy.c
new file mode 100644
index 0000000000..e8fdf94e03
--- /dev/null
+++ b/src/mod/codecs/mod_isac/energy.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_Energy().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_Word32 WebRtcSpl_Energy(WebRtc_Word16* vector, int vector_length, int* scale_factor)
+{
+ WebRtc_Word32 en = 0;
+ int i;
+ int scaling = WebRtcSpl_GetScalingSquare(vector, vector_length, vector_length);
+ int looptimes = vector_length;
+ WebRtc_Word16 *vectorptr = vector;
+
+ for (i = 0; i < looptimes; i++)
+ {
+ en += WEBRTC_SPL_MUL_16_16_RSFT(*vectorptr, *vectorptr, scaling);
+ vectorptr++;
+ }
+ *scale_factor = scaling;
+
+ return en;
+}
diff --git a/src/mod/codecs/mod_isac/entropy_coding.c b/src/mod/codecs/mod_isac/entropy_coding.c
new file mode 100644
index 0000000000..a7299447f1
--- /dev/null
+++ b/src/mod/codecs/mod_isac/entropy_coding.c
@@ -0,0 +1,2748 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.c
+ *
+ * This header file defines all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+
+#include "entropy_coding.h"
+#include "settings.h"
+#include "arith_routines.h"
+#include "signal_processing_library.h"
+#include "spectrum_ar_model_tables.h"
+#include "lpc_tables.h"
+#include "pitch_gain_tables.h"
+#include "pitch_lag_tables.h"
+#include "encode_lpc_swb.h"
+#include "lpc_shape_swb12_tables.h"
+#include "lpc_shape_swb16_tables.h"
+#include "lpc_gain_swb_tables.h"
+#include "os_specific_inline.h"
+
+#include
+#include
+
+static const WebRtc_UWord16 kLpcVecPerSegmentUb12 = 5;
+static const WebRtc_UWord16 kLpcVecPerSegmentUb16 = 4;
+
+/* coefficients for the stepwise rate estimation */
+static const WebRtc_Word32 kRPointsQ10[100] = {
+ 14495, 14295, 14112, 13944, 13788, 13643, 13459, 13276, 13195, 13239,
+ 13243, 13191, 13133, 13216, 13263, 13330, 13316, 13242, 13191, 13106,
+ 12942, 12669, 12291, 11840, 11361, 10795, 10192, 9561, 8934, 8335,
+ 7750, 7161, 6589, 6062, 5570, 5048, 4548, 4069, 3587, 3143,
+ 2717, 2305, 1915, 1557, 1235, 963, 720, 541, 423, 366,
+ 369, 435, 561, 750, 1001, 1304, 1626, 1989, 2381, 2793,
+ 3219, 3656, 4134, 4612, 5106, 5629, 6122, 6644, 7216, 7801,
+ 8386, 8987, 9630, 10255, 10897, 11490, 11950, 12397, 12752, 12999,
+ 13175, 13258, 13323, 13290, 13296, 13335, 13113, 13255, 13347, 13355,
+ 13298, 13247, 13313, 13155, 13267, 13313, 13374, 13446, 13525, 13609};
+
+
+/* cdf array for encoder bandwidth (12 vs 16 kHz) indicator */
+static const WebRtc_UWord16 kOneBitEqualProbCdf[3] = {
+ 0, 32768, 65535 };
+
+/* pointer to cdf array for encoder bandwidth (12 vs 16 kHz) indicator */
+static const WebRtc_UWord16 *kOneBitEqualProbCdf_ptr[1] = {
+ kOneBitEqualProbCdf };
+
+/* initial cdf index for decoder of encoded bandwidth (12 vs 16 kHz) indicator */
+static const WebRtc_UWord16 kOneBitEqualProbInitIndex[1] = {1};
+
+
+/* coefficients for the stepwise rate estimation */
+
+
+static const WebRtc_Word32 acnQ10 = 426;
+static const WebRtc_Word32 bcnQ10 = -581224;
+static const WebRtc_Word32 ccnQ10 = 722631;
+static const WebRtc_Word32 lbcnQ10 = -402874;
+#define DPMIN_Q10 -10240 // -10.00 in Q10
+#define DPMAX_Q10 10240 // 10.00 in Q10
+#define MINBITS_Q10 10240 /* 10.0 in Q10 */
+#define IS_SWB_12KHZ 1
+
+__inline WebRtc_UWord32 stepwise(WebRtc_Word32 dinQ10) {
+
+ WebRtc_Word32 ind, diQ10, dtQ10;
+
+ diQ10 = dinQ10;
+ if (diQ10 < DPMIN_Q10)
+ diQ10 = DPMIN_Q10;
+ if (diQ10 >= DPMAX_Q10)
+ diQ10 = DPMAX_Q10 - 1;
+
+ dtQ10 = diQ10 - DPMIN_Q10; /* Q10 + Q10 = Q10 */
+ ind = (dtQ10 * 5) >> 10; /* 2^10 / 5 = 0.2 in Q10 */
+ /* Q10 -> Q0 */
+
+ return kRPointsQ10[ind];
+}
+
+
+__inline short log2_Q10_B( int x )
+{
+ int zeros;
+ short frac;
+
+ zeros = WebRtcSpl_NormU32( x );
+ frac = ((unsigned int)(x << zeros) & 0x7FFFFFFF) >> 21;
+ return (short) (((31 - zeros) << 10) + frac);
+}
+
+
+
+/* compute correlation from power spectrum */
+static void WebRtcIsac_FindCorrelation(WebRtc_Word32 *PSpecQ12, WebRtc_Word32 *CorrQ7)
+{
+ WebRtc_Word32 summ[FRAMESAMPLES/8];
+ WebRtc_Word32 diff[FRAMESAMPLES/8];
+ const WebRtc_Word16 *CS_ptrQ9;
+ WebRtc_Word32 sum;
+ int k, n;
+
+ for (k = 0; k < FRAMESAMPLES/8; k++) {
+ summ[k] = (PSpecQ12[k] + PSpecQ12[FRAMESAMPLES_QUARTER-1 - k] + 16) >> 5;
+ diff[k] = (PSpecQ12[k] - PSpecQ12[FRAMESAMPLES_QUARTER-1 - k] + 16) >> 5;
+ }
+
+ sum = 2;
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += summ[n];
+ CorrQ7[0] = sum;
+
+ for (k = 0; k < AR_ORDER; k += 2) {
+ sum = 0;
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ sum += (CS_ptrQ9[n] * diff[n] + 256) >> 9;
+ CorrQ7[k+1] = sum;
+ }
+
+ for (k=1; k> 9;
+ CorrQ7[k+1] = sum;
+ }
+}
+
+/* compute inverse AR power spectrum */
+/* Changed to the function used in iSAC FIX for compatibility reasons */
+static void WebRtcIsac_FindInvArSpec(const WebRtc_Word16 *ARCoefQ12,
+ const WebRtc_Word32 gainQ10,
+ WebRtc_Word32 *CurveQ16)
+{
+ WebRtc_Word32 CorrQ11[AR_ORDER+1];
+ WebRtc_Word32 sum, tmpGain;
+ WebRtc_Word32 diffQ16[FRAMESAMPLES/8];
+ const WebRtc_Word16 *CS_ptrQ9;
+ int k, n;
+ WebRtc_Word16 round, shftVal = 0, sh;
+
+ sum = 0;
+ for (n = 0; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n], ARCoefQ12[n]); /* Q24 */
+ sum = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(WEBRTC_SPL_RSHIFT_W32(sum, 6), 65) + 32768, 16); /* result in Q8 */
+ CorrQ11[0] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, gainQ10) + 256, 9);
+
+ /* To avoid overflow, we shift down gainQ10 if it is large. We will not lose any precision */
+ if(gainQ10>400000){
+ tmpGain = WEBRTC_SPL_RSHIFT_W32(gainQ10, 3);
+ round = 32;
+ shftVal = 6;
+ } else {
+ tmpGain = gainQ10;
+ round = 256;
+ shftVal = 9;
+ }
+
+ for (k = 1; k < AR_ORDER+1; k++) {
+ sum = 16384;
+ for (n = k; n < AR_ORDER+1; n++)
+ sum += WEBRTC_SPL_MUL(ARCoefQ12[n-k], ARCoefQ12[n]); /* Q24 */
+ sum = WEBRTC_SPL_RSHIFT_W32(sum, 15);
+ CorrQ11[k] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(sum, tmpGain) + round, shftVal);
+ }
+ sum = WEBRTC_SPL_LSHIFT_W32(CorrQ11[0], 7);
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ CurveQ16[n] = sum;
+
+ for (k = 1; k < AR_ORDER; k += 2) {
+ //CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ CurveQ16[n] += WEBRTC_SPL_RSHIFT_W32(
+ WEBRTC_SPL_MUL(WebRtcIsac_kCos[k][n], CorrQ11[k+1]) + 2, 2);
+ }
+
+ CS_ptrQ9 = WebRtcIsac_kCos[0];
+
+ /* If CorrQ11[1] too large we avoid getting overflow in the calculation by shifting */
+ sh=WebRtcSpl_NormW32(CorrQ11[1]);
+ if (CorrQ11[1]==0) /* Use next correlation */
+ sh=WebRtcSpl_NormW32(CorrQ11[2]);
+
+ if (sh<9)
+ shftVal = 9 - sh;
+ else
+ shftVal = 0;
+
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] = WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[1], shftVal)) + 2, 2);
+ for (k = 2; k < AR_ORDER; k += 2) {
+ CS_ptrQ9 = WebRtcIsac_kCos[k];
+ for (n = 0; n < FRAMESAMPLES/8; n++)
+ diffQ16[n] += WEBRTC_SPL_RSHIFT_W32(WEBRTC_SPL_MUL(CS_ptrQ9[n], WEBRTC_SPL_RSHIFT_W32(CorrQ11[k+1], shftVal)) + 2, 2);
+ }
+
+ for (k=0; k>25); // * 128/4294967295
+
+ /* new random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither2_Q7 = (WebRtc_Word16)(((int)seed + 16777216)>>25);
+
+ shft = (seed >> 25) & 15;
+ if (shft < 5)
+ {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k+1] = dither2_Q7;
+ bufQ7[k+2] = 0;
+ }
+ else if (shft < 10)
+ {
+ bufQ7[k] = dither1_Q7;
+ bufQ7[k+1] = 0;
+ bufQ7[k+2] = dither2_Q7;
+ }
+ else
+ {
+ bufQ7[k] = 0;
+ bufQ7[k+1] = dither1_Q7;
+ bufQ7[k+2] = dither2_Q7;
+ }
+ }
+ }
+ else
+ {
+ dither_gain_Q14 = (WebRtc_Word16)(22528 - 10 * AvgPitchGain_Q12);
+
+ /* dither on half of the coefficients */
+ for (k = 0; k < length-1; k += 2)
+ {
+ /* new random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 */
+ dither1_Q7 = (WebRtc_Word16)(((int)seed + 16777216)>>25);
+
+ /* dither sample is placed in either even or odd index */
+ shft = (seed >> 25) & 1; /* either 0 or 1 */
+
+ bufQ7[k + shft] = (((dither_gain_Q14 * dither1_Q7) + 8192)>>14);
+ bufQ7[k + 1 - shft] = 0;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * GenerateDitherQ7LbUB()
+ *
+ * generate array of dither samples in Q7 There are less zeros in dither
+ * vector compared to GenerateDitherQ7Lb.
+ *
+ * A uniform random number generator with the range of [-64 64] is employed
+ * but the generated dithers are scaled by 0.35, a heuristic scaling.
+ *
+ * Input:
+ * -seed : the initial seed for the random number generator.
+ * -length : the number of dither values to be generated.
+ *
+ * Output:
+ * -bufQ7 : pointer to a buffer where dithers are written to.
+ */
+static void GenerateDitherQ7LbUB(
+ WebRtc_Word16 *bufQ7,
+ WebRtc_UWord32 seed,
+ int length)
+{
+ int k;
+ for (k = 0; k < length; k++) {
+ /* new random unsigned int */
+ seed = (seed * 196314165) + 907633515;
+
+ /* fixed-point dither sample between -64 and 64 (Q7) */
+ // * 128/4294967295
+ bufQ7[k] = (WebRtc_Word16)(((int)seed + 16777216)>>25);
+
+ // scale by 0.35
+ bufQ7[k] = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(bufQ7[k],
+ 2048, 13);
+ }
+}
+
+
+
+/*
+ * function to decode the complex spectrum from the bit stream
+ * returns the total number of bytes in the stream
+ */
+int WebRtcIsac_DecodeSpecLb(Bitstr *streamdata,
+ double *fr,
+ double *fi,
+ WebRtc_Word16 AvgPitchGain_Q12)
+{
+ WebRtc_Word16 DitherQ7[FRAMESAMPLES];
+ WebRtc_Word16 data[FRAMESAMPLES];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 gainQ10;
+ WebRtc_Word32 gain2_Q10, res;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ int k, len, i;
+
+ /* create dither signal */
+ GenerateDitherQ7Lb(DitherQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
+
+ /* decode model parameters */
+ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic decoding of spectrum */
+ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8, DitherQ7,
+ FRAMESAMPLES, !IS_SWB_12KHZ)) <1)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* subtract dither and scale down spectral samples with low SNR */
+ if (AvgPitchGain_Q12 <= 614)
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(30 << 10,
+ (WebRtc_Word16)((invARSpec2_Q16[k>>2] + (32768 + (33 << 16))) >> 16));
+ *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k+1] * gainQ10 + 512) >> 10) / 128.0;
+ *fr++ = (double)((data[k+2] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k+3] * gainQ10 + 512) >> 10) / 128.0;
+ }
+ }
+ else
+ {
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ gainQ10 = WebRtcSpl_DivW32W16ResW16(36 << 10,
+ (WebRtc_Word16)((invARSpec2_Q16[k>>2] + (32768 + (40 << 16))) >> 16));
+ *fr++ = (double)((data[ k ] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k+1] * gainQ10 + 512) >> 10) / 128.0;
+ *fr++ = (double)((data[k+2] * gainQ10 + 512) >> 10) / 128.0;
+ *fi++ = (double)((data[k+3] * gainQ10 + 512) >> 10) / 128.0;
+ }
+ }
+
+ return len;
+}
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpecUB16()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * This function is called when the codec is in 0-16 kHz bandwidth.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpecUB16(
+ Bitstr* streamdata,
+ double* fr,
+ double* fi)
+{
+ WebRtc_Word16 DitherQ7[FRAMESAMPLES];
+ WebRtc_Word16 data[FRAMESAMPLES];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word32 gain2_Q10, res;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ int k, len, i, j;
+
+ /* create dither signal */
+ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
+
+ /* decode model parameters */
+ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic decoding of spectrum */
+ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata, invARSpecQ8,
+ DitherQ7, FRAMESAMPLES, !IS_SWB_12KHZ)) <1)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ /* re-arrange DFT coefficients and scale down */
+ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++)
+ {
+ fr[j] = (double)data[ k ] / 128.0;
+ fi[j] = (double)data[k+1] / 128.0;
+ fr[(FRAMESAMPLES_HALF) - 1 - j] = (double)data[k+2] / 128.0;
+ fi[(FRAMESAMPLES_HALF) - 1 - j] = (double)data[k+3] / 128.0;
+
+ }
+ return len;
+}
+
+
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpecUB12()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * This function is called when the codec is in 0-12 kHz bandwidth.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpecUB12(
+ Bitstr *streamdata,
+ double *fr,
+ double *fi)
+{
+ WebRtc_Word16 DitherQ7[FRAMESAMPLES];
+ WebRtc_Word16 data[FRAMESAMPLES];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word32 res;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ int k, len, i;
+
+ /* create dither signal */
+ GenerateDitherQ7LbUB(DitherQ7, streamdata->W_upper, FRAMESAMPLES);
+
+ /* decode model parameters */
+ if (WebRtcIsac_DecodeRc(streamdata, RCQ15) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ if (WebRtcIsac_DecodeGain2(streamdata, &gain2_Q10) < 0)
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic decoding of spectrum */
+ if ((len = WebRtcIsac_DecLogisticMulti2(data, streamdata,
+ invARSpecQ8, DitherQ7, (FRAMESAMPLES_HALF), IS_SWB_12KHZ)) < 1)
+ {
+ return -ISAC_RANGE_ERROR_DECODE_SPECTRUM;
+ }
+
+ for (k = 0, i = 0; k < FRAMESAMPLES_HALF; k += 4)
+ {
+ fr[i] = (double)data[ k ] / 128.0;
+ fi[i] = (double)data[k+1] / 128.0;
+ i++;
+ fr[i] = (double)data[k+2] / 128.0;
+ fi[i] = (double)data[k+3] / 128.0;
+ i++;
+ }
+
+ // The second half of real and imaginary coefficients is zero. This is
+ // due to using the old FFT module which requires two signals as input
+ // while in 0-12 kHz mode we only have 8-12 kHz band, and the second signal
+ // is set to zero
+ memset(&fr[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER * sizeof(double));
+ memset(&fi[FRAMESAMPLES_QUARTER], 0, FRAMESAMPLES_QUARTER * sizeof(double));
+
+ return len;
+}
+
+
+
+
+
+int WebRtcIsac_EncodeSpecLb(const WebRtc_Word16 *fr,
+ const WebRtc_Word16 *fi,
+ Bitstr *streamdata,
+ WebRtc_Word16 AvgPitchGain_Q12)
+{
+ WebRtc_Word16 ditherQ7[FRAMESAMPLES];
+ WebRtc_Word16 dataQ7[FRAMESAMPLES];
+ WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 CorrQ7[AR_ORDER+1];
+ WebRtc_Word32 CorrQ7_norm[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word16 val;
+ WebRtc_Word32 nrg, res;
+ WebRtc_UWord32 sum;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ WebRtc_Word16 err;
+ WebRtc_UWord32 nrg_u32;
+ int shift_var;
+ int k, n, j, i;
+
+
+ /* create dither_float signal */
+ GenerateDitherQ7Lb(ditherQ7, streamdata->W_upper, FRAMESAMPLES, AvgPitchGain_Q12);
+
+ /* add dither and quantize, and compute power spectrum */
+ for (k = 0; k < FRAMESAMPLES; k += 4)
+ {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((*fi++ + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1];
+ dataQ7[k+1] = val;
+ sum += val * val;
+
+ val = ((*fr++ + ditherQ7[k+2] + 64) & 0xFF80) - ditherQ7[k+2];
+ dataQ7[k+2] = val;
+ sum += val * val;
+
+ val = ((*fi++ + ditherQ7[k+3] + 64) & 0xFF80) - ditherQ7[k+3];
+ dataQ7[k+3] = val;
+ sum += val * val;
+
+ PSpec[k>>2] = sum >> 2;
+ }
+
+ /* compute correlation from power spectrum */
+ WebRtcIsac_FindCorrelation(PSpec, CorrQ7);
+
+
+ /* find AR coefficients */
+ /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
+ shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (shift_var > 0) {
+ for (k=0; k> (-shift_var);
+ }
+ }
+
+ /* find RC coefficients */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* quantize & code RC Coefficient */
+ WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ /* compute ARCoef' * Corr * ARCoef in Q19 */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3;
+ }
+ for (n = j+1; n <= AR_ORDER; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3;
+ }
+ }
+
+ nrg_u32 = (WebRtc_UWord32)nrg;
+ if (shift_var > 0) {
+ nrg_u32 = nrg_u32 >> shift_var;
+ } else {
+ nrg_u32 = nrg_u32 << (-shift_var);
+ }
+
+ if (nrg_u32 > 0x7FFFFFFF)
+ nrg = 0x7FFFFFFF;
+ else
+ nrg = (WebRtc_Word32)nrg_u32;
+
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */
+
+ /* quantize & code gain2_Q10 */
+ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+ return -1;
+ }
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic coding of spectrum */
+ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+ FRAMESAMPLES, !IS_SWB_12KHZ);
+ if (err < 0)
+ {
+ return (err);
+ }
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpecUB16()
+ * Quantize and encode real and imaginary part of the DFT coefficients.
+ * This function is called when the codec is in 0-16 kHz bandwidth.
+ * The real and imaginary part are computed by calling WebRtcIsac_Time2Spec().
+ *
+ *
+ * Input:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are stored.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are stored.
+ *
+ * Output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpecUB16(
+ const WebRtc_Word16* fr,
+ const WebRtc_Word16* fi,
+ Bitstr* streamdata)
+{
+ WebRtc_Word16 ditherQ7[FRAMESAMPLES];
+ WebRtc_Word16 dataQ7[FRAMESAMPLES];
+ WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 CorrQ7[AR_ORDER+1];
+ WebRtc_Word32 CorrQ7_norm[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word16 val;
+ WebRtc_Word32 nrg, res;
+ WebRtc_UWord32 sum;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ WebRtc_Word16 err;
+ WebRtc_UWord32 nrg_u32;
+ int shift_var;
+ int k, n, j, i;
+
+ /* create dither_float signal */
+ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
+
+ /* add dither and quantize, and compute power spectrum */
+ for (j = 0, k = 0; k < FRAMESAMPLES; k += 4, j++)
+ {
+ val = ((fr[j] + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = val * val;
+
+ val = ((fi[j] + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1];
+ dataQ7[k+1] = val;
+ sum += val * val;
+
+ val = ((fr[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k+2] + 64) &
+ 0xFF80) - ditherQ7[k+2];
+ dataQ7[k+2] = val;
+ sum += val * val;
+
+ val = ((fi[(FRAMESAMPLES_HALF) - 1 - j] + ditherQ7[k+3] + 64) &
+ 0xFF80) - ditherQ7[k+3];
+ dataQ7[k+3] = val;
+ sum += val * val;
+
+ PSpec[k>>2] = sum >> 2;
+ }
+
+ /* compute correlation from power spectrum */
+ WebRtcIsac_FindCorrelation(PSpec, CorrQ7);
+
+
+ /* find AR coefficients
+ number of bit shifts to 14-bit normalize CorrQ7[0]
+ (leaving room for sign) */
+ shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (shift_var > 0) {
+ for (k=0; k> (-shift_var);
+ }
+ }
+
+ /* find RC coefficients */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* quantize & code RC Coef */
+ WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+ /* compute ARCoef' * Corr * ARCoef in Q19 */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] +
+ 256) >> 9) + 4 ) >> 3;
+ }
+ for (n = j+1; n <= AR_ORDER; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] +
+ 256) >> 9) + 4 ) >> 3;
+ }
+ }
+ nrg_u32 = (WebRtc_UWord32)nrg;
+ if (shift_var > 0) {
+ nrg_u32 = nrg_u32 >> shift_var;
+ } else {
+ nrg_u32 = nrg_u32 << (-shift_var);
+ }
+
+ if (nrg_u32 > 0x7FFFFFFF)
+ nrg = 0x7FFFFFFF;
+ else
+ nrg = (WebRtc_Word32)nrg_u32;
+
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */
+
+ /* quantize & code gain2_Q10 */
+ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+ return -1;
+ }
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic coding of spectrum */
+ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+ FRAMESAMPLES, !IS_SWB_12KHZ);
+ if (err < 0)
+ {
+ return (err);
+ }
+
+ return 0;
+}
+
+
+
+
+int WebRtcIsac_EncodeSpecUB12(const WebRtc_Word16 *fr,
+ const WebRtc_Word16 *fi,
+ Bitstr *streamdata)
+{
+ WebRtc_Word16 ditherQ7[FRAMESAMPLES];
+ WebRtc_Word16 dataQ7[FRAMESAMPLES];
+ WebRtc_Word32 PSpec[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 invARSpec2_Q16[FRAMESAMPLES_QUARTER];
+ WebRtc_UWord16 invARSpecQ8[FRAMESAMPLES_QUARTER];
+ WebRtc_Word32 CorrQ7[AR_ORDER+1];
+ WebRtc_Word32 CorrQ7_norm[AR_ORDER+1];
+ WebRtc_Word16 RCQ15[AR_ORDER];
+ WebRtc_Word16 ARCoefQ12[AR_ORDER+1];
+ WebRtc_Word32 gain2_Q10;
+ WebRtc_Word16 val;
+ WebRtc_Word32 nrg, res;
+ WebRtc_UWord32 sum;
+ WebRtc_Word32 in_sqrt;
+ WebRtc_Word32 newRes;
+ WebRtc_Word16 err;
+ int shift_var;
+ int k, n, j, i;
+ WebRtc_UWord32 nrg_u32;
+
+ /* create dither_float signal */
+ GenerateDitherQ7LbUB(ditherQ7, streamdata->W_upper, FRAMESAMPLES);
+
+ /* add dither and quantize, and compute power spectrum */
+ for (k = 0, j = 0; k < (FRAMESAMPLES_HALF); k += 4)
+ {
+ val = ((*fr++ + ditherQ7[k] + 64) & 0xFF80) - ditherQ7[k];
+ dataQ7[k] = val;
+ sum = (val) * (val);
+
+ val = ((*fi++ + ditherQ7[k+1] + 64) & 0xFF80) - ditherQ7[k+1];
+ dataQ7[k+1] = val;
+ sum += (val) * (val);
+
+ if(j < FRAMESAMPLES_QUARTER)
+ {
+ PSpec[j] = sum >> 1;
+ j++;
+ }
+
+ val = ((*fr++ + ditherQ7[k+2] + 64) & 0xFF80) - ditherQ7[k+2];
+ dataQ7[k+2] = val;
+ sum = (val) * (val);
+
+ val = ((*fi++ + ditherQ7[k+3] + 64) & 0xFF80) - ditherQ7[k+3];
+ dataQ7[k+3] = val;
+ sum += (val) * (val);
+
+ if(j < FRAMESAMPLES_QUARTER)
+ {
+ PSpec[j] = sum >> 1;
+ j++;
+ }
+ }
+ /* compute correlation from power spectrum */
+ WebRtcIsac_FindCorrelation(PSpec, CorrQ7);
+
+
+ /* find AR coefficients */
+ /* number of bit shifts to 14-bit normalize CorrQ7[0] (leaving room for sign) */
+ shift_var = WebRtcSpl_NormW32(CorrQ7[0]) - 18;
+
+ if (shift_var > 0) {
+ for (k=0; k> (-shift_var);
+ }
+ }
+
+ /* find RC coefficients */
+ WebRtcSpl_AutoCorrToReflCoef(CorrQ7_norm, AR_ORDER, RCQ15);
+
+ /* quantize & code RC Coef */
+ WebRtcIsac_EncodeRc(RCQ15, streamdata);
+
+
+ /* RC -> AR coefficients */
+ WebRtcSpl_ReflCoefToLpc(RCQ15, AR_ORDER, ARCoefQ12);
+
+
+ /* compute ARCoef' * Corr * ARCoef in Q19 */
+ nrg = 0;
+ for (j = 0; j <= AR_ORDER; j++) {
+ for (n = 0; n <= j; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[j-n] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3;
+ }
+ for (n = j+1; n <= AR_ORDER; n++) {
+ nrg += ( ARCoefQ12[j] * ((CorrQ7_norm[n-j] * ARCoefQ12[n] + 256) >> 9) + 4 ) >> 3;
+ }
+ }
+
+ nrg_u32 = (WebRtc_UWord32)nrg;
+ if (shift_var > 0) {
+ nrg_u32 = nrg_u32 >> shift_var;
+ } else {
+ nrg_u32 = nrg_u32 << (-shift_var);
+ }
+
+ if (nrg_u32 > 0x7FFFFFFF) {
+ nrg = 0x7FFFFFFF;
+ } else {
+ nrg = (WebRtc_Word32)nrg_u32;
+ }
+
+ gain2_Q10 = WebRtcSpl_DivResultInQ31(FRAMESAMPLES_QUARTER, nrg); /* also shifts 31 bits to the left! */
+
+ /* quantize & code gain2_Q10 */
+ if (WebRtcIsac_EncodeGain2(&gain2_Q10, streamdata)) {
+ return -1;
+ }
+
+ /* compute inverse AR power spectrum */
+ WebRtcIsac_FindInvArSpec(ARCoefQ12, gain2_Q10, invARSpec2_Q16);
+
+ /* convert to magnitude spectrum, by doing square-roots (modified from SPLIB) */
+ res = 1 << (WebRtcSpl_GetSizeInBits(invARSpec2_Q16[0]) >> 1);
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++)
+ {
+ in_sqrt = invARSpec2_Q16[k];
+ i = 10;
+
+ /* Negative values make no sense for a real sqrt-function. */
+ if (in_sqrt<0)
+ in_sqrt=-in_sqrt;
+
+ newRes = (in_sqrt / res + res) >> 1;
+ do
+ {
+ res = newRes;
+ newRes = (in_sqrt / res + res) >> 1;
+ } while (newRes != res && i-- > 0);
+
+ invARSpecQ8[k] = (WebRtc_Word16)newRes;
+ }
+
+ /* arithmetic coding of spectrum */
+ err = WebRtcIsac_EncLogisticMulti2(streamdata, dataQ7, invARSpecQ8,
+ (FRAMESAMPLES_HALF), IS_SWB_12KHZ);
+ if (err < 0)
+ {
+ return (err);
+ }
+
+ return 0;
+}
+
+
+
+/* step-up */
+void WebRtcIsac_Rc2Poly(double *RC, int N, double *a)
+{
+ int m, k;
+ double tmp[MAX_AR_MODEL_ORDER];
+
+ a[0] = 1.0;
+ tmp[0] = 1.0;
+ for (m=1; m<=N; m++) {
+ /* copy */
+ for (k=1; k0; m--) {
+ tmp_inv = 1.0 / (1.0 - RC[m]*RC[m]);
+ for (k=1; k<=m; k++)
+ tmp[k] = (a[k] - RC[m] * a[m-k+1]) * tmp_inv;
+
+ for (k=1; k WebRtcIsac_kQKltMaxIndGain[k])
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[bmodel][k]+index_g[k];
+ pos = WebRtcIsac_kQKltOfLevelsGain[bmodel] + index_ovr_g[k];
+
+ /* determine number of bits */
+ sum = WebRtcIsac_kQKltCodeLenGain[pos];
+ Bits += sum;
+ }
+
+ for (k=0; k WebRtcIsac_kQKltMaxIndShape[k])
+ index_s[k] = WebRtcIsac_kQKltMaxIndShape[k];
+ index_ovr_s[k] = WebRtcIsac_kQKltOffsetShape[bmodel][k]+index_s[k];
+ pos = WebRtcIsac_kQKltOfLevelsShape[bmodel] + index_ovr_s[k];
+ sum = WebRtcIsac_kQKltCodeLenShape[pos];
+ Bits += sum;
+ }
+
+
+ /* Only one model remains in this version of the code, model = 0 */
+ *model=bmodel;
+ *size=Bits;
+
+ /* entropy coding of model number */
+ WebRtcIsac_EncHistMulti(streamdata, model, WebRtcIsac_kQKltModelCdfPtr, 1);
+
+ /* entropy coding of quantization indices - shape only */
+ WebRtcIsac_EncHistMulti(streamdata, index_s, WebRtcIsac_kQKltCdfPtrShape[bmodel], KLT_ORDER_SHAPE);
+
+ /* Save data for creation of multiple bit streams */
+ encData->LPCmodel[encData->startIdx] = 0;
+ for (k=0; kLPCindex_s[KLT_ORDER_SHAPE*encData->startIdx + k] = index_s[k];
+ }
+
+ /* find quantization levels for shape coefficients */
+ for (k=0; kLPCcoeffs_lo[(ORDERLO+1)*SUBFRAMES*encData->startIdx + k] = LPCCoef_lo[k];
+ }
+ for (k=0; k<(ORDERHI+1)*SUBFRAMES; k++) {
+ encData->LPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*encData->startIdx + k] = LPCCoef_hi[k];
+ }
+}
+
+
+WebRtc_Word16
+WebRtcIsac_EncodeLpcUB(
+ double* lpcVecs,
+ Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ WebRtc_Word16 bandwidth,
+ ISACUBSaveEncDataStruct* encData)
+{
+
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int idx[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int interpolCntr;
+
+ WebRtcIsac_Poly2LarUB(lpcVecs, bandwidth);
+ WebRtcIsac_RemoveLarMean(lpcVecs, bandwidth);
+ WebRtcIsac_DecorrelateIntraVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_DecorrelateInterVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_QuantizeUncorrLar(lpcVecs, idx, bandwidth);
+
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ // Stor the indices to be used for multiple encoding.
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME *
+ sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb12,
+ UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+ for(interpolCntr = 0; interpolCntr < UB_INTERPOL_SEGMENTS; interpolCntr++)
+ {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs,
+ interpolLPCCoeff, kLpcVecPerSegmentUb12 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb12 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ case isac16kHz:
+ {
+ // Stor the indices to be used for multiple encoding.
+ memcpy(encData->indexLPCShape, idx, UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME *
+ sizeof(int));
+ WebRtcIsac_EncHistMulti(streamdata, idx, WebRtcIsac_kLpcShapeCdfMatUb16,
+ UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+ for(interpolCntr = 0; interpolCntr < UB16_INTERPOL_SEGMENTS; interpolCntr++)
+ {
+ WebRtcIsac_Lar2PolyInterpolUB(lpcVecs,
+ interpolLPCCoeff, kLpcVecPerSegmentUb16 + 1);
+ lpcVecs += UB_LPC_ORDER;
+ interpolLPCCoeff += (kLpcVecPerSegmentUb16 * (UB_LPC_ORDER + 1));
+ }
+ break;
+ }
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void WebRtcIsac_EncodeLpcGainLb(double *LPCCoef_lo, double *LPCCoef_hi, int model, Bitstr *streamdata, ISAC_SaveEncData_t* encData) {
+
+ int j, k, n, pos, pos2, posg, offsg, offs2;
+ int index_g[KLT_ORDER_GAIN];
+ int index_ovr_g[KLT_ORDER_GAIN];
+ double tmpcoeffs_g[KLT_ORDER_GAIN];
+ double tmpcoeffs2_g[KLT_ORDER_GAIN];
+ double sum;
+
+ /* log gains, mean removal and scaling */
+ posg = 0;
+ for (k=0; k WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[model][k]+index_g[k];
+
+ /* find quantization levels for coefficients */
+ tmpcoeffs_g[WebRtcIsac_kQKltSelIndGain[k]] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOfLevelsGain[model]+index_ovr_g[k]];
+
+ /* Save data for creation of multiple bit streams */
+ encData->LPCindex_g[KLT_ORDER_GAIN*encData->startIdx + k] = index_g[k];
+ }
+
+
+ /* entropy coding of quantization indices - gain */
+ WebRtcIsac_EncHistMulti(streamdata, index_g, WebRtcIsac_kQKltCdfPtrGain[model], KLT_ORDER_GAIN);
+
+ /* find quantization levels for coefficients */
+
+ /* left transform */
+ offsg = 0;
+ posg = 0;
+ for (j=0; j WebRtcIsac_kQArBoundaryLevels[index[k]])
+ {
+ while (RCQ15[k] > WebRtcIsac_kQArBoundaryLevels[index[k] + 1])
+ index[k]++;
+ }
+ else
+ {
+ while (RCQ15[k] < WebRtcIsac_kQArBoundaryLevels[--index[k]]) ;
+ }
+
+ RCQ15[k] = *(WebRtcIsac_kQArRcLevelsPtr[k] + index[k]);
+ }
+
+
+ /* entropy coding of quantization indices */
+ WebRtcIsac_EncHistMulti(streamdata, index, WebRtcIsac_kQArRcCdfPtr, AR_ORDER);
+}
+
+
+/* decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr *streamdata, WebRtc_Word32 *gainQ10)
+{
+ int index, err;
+
+ /* entropy decoding of quantization index */
+ err = WebRtcIsac_DecHistOneStepMulti(&index, streamdata, WebRtcIsac_kQGainCdf_ptr,
+ WebRtcIsac_kQGainInitIndex, 1);
+ if (err<0) // error check
+ return err;
+
+ /* find quantization level */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+
+ return 0;
+}
+
+
+
+/* quantize & code squared Gain */
+int WebRtcIsac_EncodeGain2(WebRtc_Word32 *gainQ10, Bitstr *streamdata)
+{
+ int index;
+
+
+ /* find quantization index */
+ index = WebRtcIsac_kQGainInitIndex[0];
+ if (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index])
+ {
+ while (*gainQ10 > WebRtcIsac_kQGain2BoundaryLevels[index + 1])
+ index++;
+ }
+ else
+ {
+ while (*gainQ10 < WebRtcIsac_kQGain2BoundaryLevels[--index]) ;
+ }
+
+ /* dequantize */
+ *gainQ10 = WebRtcIsac_kQGain2Levels[index];
+
+
+ /* entropy coding of quantization index */
+ WebRtcIsac_EncHistMulti(streamdata, &index, WebRtcIsac_kQGainCdf_ptr, 1);
+
+ return 0;
+}
+
+
+/* code and decode Pitch Gains and Lags functions */
+
+/* decode & dequantize Pitch Gains */
+int WebRtcIsac_DecodePitchGain(Bitstr *streamdata, WebRtc_Word16 *PitchGains_Q12)
+{
+ int index_comb, err;
+ const WebRtc_UWord16 *WebRtcIsac_kQPitchGainCdf_ptr[1];
+
+ /* entropy decoding of quantization indices */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ err = WebRtcIsac_DecHistBisectMulti(&index_comb, streamdata, WebRtcIsac_kQPitchGainCdf_ptr, WebRtcIsac_kQCdfTableSizeGain, 1);
+ /* error check, Q_mean_Gain.. tables are of size 144 */
+ if ((err<0) || (index_comb<0) || (index_comb>144))
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_GAIN;
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+
+ return 0;
+}
+
+
+/* quantize & code Pitch Gains */
+void WebRtcIsac_EncodePitchGain(WebRtc_Word16 *PitchGains_Q12, Bitstr *streamdata, ISAC_SaveEncData_t* encData)
+{
+ int k,j;
+ double C;
+ double S[PITCH_SUBFRAMES];
+ int index[3];
+ int index_comb;
+ const WebRtc_UWord16 *WebRtcIsac_kQPitchGainCdf_ptr[1];
+ double PitchGains[PITCH_SUBFRAMES] = {0,0,0,0};
+
+ /* take the asin */
+ for (k=0; k WebRtcIsac_kIndexUpperLimitGain[k]) index[k] = WebRtcIsac_kIndexUpperLimitGain[k];
+ index[k] -= WebRtcIsac_kIndexLowerLimitGain[k];
+ }
+
+ /* calculate unique overall index */
+ index_comb = WebRtcIsac_kIndexMultsGain[0] * index[0] + WebRtcIsac_kIndexMultsGain[1] * index[1] + index[2];
+
+ /* unquantize back to pitch gains by table look-up */
+ PitchGains_Q12[0] = WebRtcIsac_kQMeanGain1Q12[index_comb];
+ PitchGains_Q12[1] = WebRtcIsac_kQMeanGain2Q12[index_comb];
+ PitchGains_Q12[2] = WebRtcIsac_kQMeanGain3Q12[index_comb];
+ PitchGains_Q12[3] = WebRtcIsac_kQMeanGain4Q12[index_comb];
+
+ /* entropy coding of quantization pitch gains */
+ *WebRtcIsac_kQPitchGainCdf_ptr = WebRtcIsac_kQPitchGainCdf;
+ WebRtcIsac_EncHistMulti(streamdata, &index_comb, WebRtcIsac_kQPitchGainCdf_ptr, 1);
+ encData->pitchGain_index[encData->startIdx] = index_comb;
+
+}
+
+
+
+/* Pitch LAG */
+
+
+/* decode & dequantize Pitch Lags */
+int WebRtcIsac_DecodePitchLag(Bitstr *streamdata, WebRtc_Word16 *PitchGain_Q12, double *PitchLags)
+{
+ int k, err;
+ double StepSize;
+ double C;
+ int index[PITCH_SUBFRAMES];
+ double mean_gain;
+ const double *mean_val2, *mean_val3, *mean_val4;
+ const WebRtc_Word16 *lower_limit;
+ const WebRtc_UWord16 *init_index;
+ const WebRtc_UWord16 *cdf_size;
+ const WebRtc_UWord16 **cdf;
+
+ //(Y)
+ double PitchGain[4]={0,0,0,0};
+ //
+
+ /* compute mean pitch gain */
+ mean_gain = 0.0;
+ for (k = 0; k < 4; k++)
+ {
+ //(Y)
+ PitchGain[k] = ((float)PitchGain_Q12[k])/4096;
+ //(Y)
+ mean_gain += PitchGain[k];
+ }
+ mean_gain /= 4.0;
+
+ /* voicing classificiation */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ init_index = WebRtcIsac_kQInitIndexLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ init_index = WebRtcIsac_kQInitIndexLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ cdf_size = WebRtcIsac_kQPitchLagCdfSizeHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ init_index = WebRtcIsac_kQInitIndexLagHi;
+ }
+
+ /* entropy decoding of quantization indices */
+ err = WebRtcIsac_DecHistBisectMulti(index, streamdata, cdf, cdf_size, 1);
+ if ((err<0) || (index[0]<0)) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+ err = WebRtcIsac_DecHistOneStepMulti(index+1, streamdata, cdf+1, init_index, 3);
+ if (err<0) // error check
+ return -ISAC_RANGE_ERROR_DECODE_PITCH_LAG;
+
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k=0; kmeanGain[encData->startIdx] = mean_gain;
+
+ /* voicing classification */
+ if (mean_gain < 0.2) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeLo;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrLo;
+ mean_val2 = WebRtcIsac_kQMeanLag2Lo;
+ mean_val3 = WebRtcIsac_kQMeanLag3Lo;
+ mean_val4 = WebRtcIsac_kQMeanLag4Lo;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagLo;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagLo;
+ } else if (mean_gain < 0.4) {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeMid;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrMid;
+ mean_val2 = WebRtcIsac_kQMeanLag2Mid;
+ mean_val3 = WebRtcIsac_kQMeanLag3Mid;
+ mean_val4 = WebRtcIsac_kQMeanLag4Mid;
+ lower_limit = WebRtcIsac_kQIndexLowerLimitLagMid;
+ upper_limit = WebRtcIsac_kQIndexUpperLimitLagMid;
+ } else {
+ StepSize = WebRtcIsac_kQPitchLagStepsizeHi;
+ cdf = WebRtcIsac_kQPitchLagCdfPtrHi;
+ mean_val2 = WebRtcIsac_kQMeanLag2Hi;
+ mean_val3 = WebRtcIsac_kQMeanLag3Hi;
+ mean_val4 = WebRtcIsac_kQMeanLag4Hi;
+ lower_limit = WebRtcIsac_kQindexLowerLimitLagHi;
+ upper_limit = WebRtcIsac_kQindexUpperLimitLagHi;
+ }
+
+
+ /* find quantization index */
+ for (k=0; k<4; k++)
+ {
+ /* transform */
+ C = 0.0;
+ for (j=0; j upper_limit[k]) index[k] = upper_limit[k];
+ index[k] -= lower_limit[k];
+
+ /* Save data for creation of multiple bit streams */
+ encData->pitchIndex[PITCH_SUBFRAMES*encData->startIdx + k] = index[k];
+ }
+
+ /* unquantize back to transform coefficients and do the inverse transform: S = T'*C */
+ C = (index[0] + lower_limit[0]) * StepSize;
+ for (k=0; k WebRtcIsac_kQKltMaxIndGain[k]) {
+ index_g[k] = WebRtcIsac_kQKltMaxIndGain[k];
+ }
+ index_ovr_g[k] = WebRtcIsac_kQKltOffsetGain[model][k]+index_g[k];
+
+ /* find quantization levels for coefficients */
+ tmpcoeffs_g[WebRtcIsac_kQKltSelIndGain[k]] = WebRtcIsac_kQKltLevelsGain[WebRtcIsac_kQKltOfLevelsGain[model]+index_ovr_g[k]];
+ }
+}
+
+
+/* decode & dequantize LPC Coef */
+int
+WebRtcIsac_DecodeLpcCoefUB(
+ Bitstr* streamdata,
+ double* lpcVecs,
+ double* percepFilterGains,
+ WebRtc_Word16 bandwidth)
+{
+ int index_s[KLT_ORDER_SHAPE];
+
+ double U[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ int err;
+
+ /* entropy decoding of quantization indices */
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ err = WebRtcIsac_DecHistOneStepMulti(index_s, streamdata,
+ WebRtcIsac_kLpcShapeCdfMatUb12, WebRtcIsac_kLpcShapeEntropySearchUb12,
+ UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME);
+ break;
+ }
+ case isac16kHz:
+ {
+ err = WebRtcIsac_DecHistOneStepMulti(index_s, streamdata,
+ WebRtcIsac_kLpcShapeCdfMatUb16, WebRtcIsac_kLpcShapeEntropySearchUb16,
+ UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if (err<0) // error check
+ {
+ return err;
+ }
+
+ WebRtcIsac_DequantizeLpcParam(index_s, lpcVecs, bandwidth);
+ WebRtcIsac_CorrelateInterVec(lpcVecs, U, bandwidth);
+ WebRtcIsac_CorrelateIntraVec(U, lpcVecs, bandwidth);
+ WebRtcIsac_AddLarMean(lpcVecs, bandwidth);
+
+
+ WebRtcIsac_DecodeLpcGainUb(percepFilterGains, streamdata);
+
+ if(bandwidth == isac16kHz)
+ {
+ // decode another set of Gains
+ WebRtcIsac_DecodeLpcGainUb(&percepFilterGains[SUBFRAMES], streamdata);
+ }
+
+ return 0;
+}
+
+WebRtc_Word16
+WebRtcIsac_EncodeBandwidth(
+ enum ISACBandwidth bandwidth,
+ Bitstr* streamData)
+{
+ int bandwidthMode;
+ switch(bandwidth)
+ {
+ case isac12kHz:
+ {
+ bandwidthMode = 0;
+ break;
+ }
+ case isac16kHz:
+ {
+ bandwidthMode = 1;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_ENCODER_BANDWIDTH;
+ }
+
+ WebRtcIsac_EncHistMulti(streamData, &bandwidthMode,
+ kOneBitEqualProbCdf_ptr, 1);
+ return 0;
+}
+
+WebRtc_Word16
+WebRtcIsac_DecodeBandwidth(
+ Bitstr* streamData,
+ enum ISACBandwidth* bandwidth)
+{
+ int bandwidthMode;
+
+ if(WebRtcIsac_DecHistOneStepMulti(&bandwidthMode, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0)
+ {
+ // error check
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+
+ switch(bandwidthMode)
+ {
+ case 0:
+ {
+ *bandwidth = isac12kHz;
+ break;
+ }
+ case 1:
+ {
+ *bandwidth = isac16kHz;
+ break;
+ }
+ default:
+ return -ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER;
+ }
+ return 0;
+}
+
+WebRtc_Word16
+WebRtcIsac_EncodeJitterInfo(
+ WebRtc_Word32 jitterIndex,
+ Bitstr* streamData)
+{
+ // This is to avoid LINUX warning until we change 'int' to
+ // 'Word32'
+ int intVar;
+
+ if((jitterIndex < 0) || (jitterIndex > 1))
+ {
+ return -1;
+ }
+ intVar = (int)(jitterIndex);
+ // Use the same CDF table as for bandwidth
+ // both take two values with equal probability
+ WebRtcIsac_EncHistMulti(streamData, &intVar,
+ kOneBitEqualProbCdf_ptr, 1);
+ return 0;
+
+}
+
+WebRtc_Word16
+WebRtcIsac_DecodeJitterInfo(
+ Bitstr* streamData,
+ WebRtc_Word32* jitterInfo)
+{
+ int intVar;
+
+ // Use the same CDF table as for bandwidth
+ // both take two values with equal probability
+ if(WebRtcIsac_DecHistOneStepMulti(&intVar, streamData,
+ kOneBitEqualProbCdf_ptr,
+ kOneBitEqualProbInitIndex, 1) < 0)
+ {
+ // error check
+ return -ISAC_RANGE_ERROR_DECODE_BANDWITH;
+ }
+ *jitterInfo = (WebRtc_Word16)(intVar);
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/entropy_coding.h b/src/mod/codecs/mod_isac/entropy_coding.h
new file mode 100644
index 0000000000..8446bcf3e5
--- /dev/null
+++ b/src/mod/codecs/mod_isac/entropy_coding.h
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * entropy_coding.h
+ *
+ * This header file declares all of the functions used to arithmetically
+ * encode the iSAC bistream
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_
+
+#include "structs.h"
+
+/* decode complex spectrum (return number of bytes in stream) */
+int WebRtcIsac_DecodeSpecLb(Bitstr *streamdata,
+ double *fr,
+ double *fi,
+ WebRtc_Word16 AvgPitchGain_Q12);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpecUB16()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * This function is called when the codec is in 0-16 kHz bandwidth.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpecUB16(
+ Bitstr* streamdata,
+ double* fr,
+ double* fi);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeSpecUB12()
+ * Decode real and imaginary part of the DFT coefficients, given a bit-stream.
+ * This function is called when the codec is in 0-12 kHz bandwidth.
+ * The decoded DFT coefficient can be transformed to time domain by
+ * WebRtcIsac_Time2Spec().
+ *
+ * Input:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are written to.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are written to.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_DecodeSpecUB12(
+ Bitstr* streamdata,
+ double* fr,
+ double* fi);
+
+
+/* encode complex spectrum */
+int WebRtcIsac_EncodeSpecLb(const WebRtc_Word16* fr,
+ const WebRtc_Word16* fi,
+ Bitstr* streamdata,
+ WebRtc_Word16 AvgPitchGain_Q12);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpecUB16()
+ * Quantize and encode real and imaginary part of the DFT coefficients.
+ * This function is called when the codec is in 0-16 kHz bandwidth.
+ * The real and imaginary part are computed by calling WebRtcIsac_Time2Spec().
+ *
+ *
+ * Input:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are stored.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are stored.
+ *
+ * Output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpecUB16(
+ const WebRtc_Word16* fr,
+ const WebRtc_Word16* fi,
+ Bitstr* streamdata);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeSpecUB12()
+ * Quantize and encode real and imaginary part of the DFT coefficients.
+ * This function is called when the codec is in 0-12 kHz bandwidth.
+ * The real and imaginary part are computed by calling WebRtcIsac_Time2Spec().
+ *
+ *
+ * Input:
+ * -*fr : pointer to a buffer where the real part of DFT
+ * coefficients are stored.
+ * -*fi : pointer to a buffer where the imaginary part
+ * of DFT coefficients are stored.
+ *
+ * Output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : < 0 if an error occures
+ * 0 if succeeded.
+ */
+int WebRtcIsac_EncodeSpecUB12(
+ const WebRtc_Word16* fr,
+ const WebRtc_Word16* fi,
+ Bitstr* streamdata);
+
+
+/* decode & dequantize LPC Coef */
+int WebRtcIsac_DecodeLpcCoef(Bitstr *streamdata, double *LPCCoef, int *outmodel);
+int WebRtcIsac_DecodeLpcCoefUB(
+ Bitstr* streamdata,
+ double* lpcVecs,
+ double* percepFilterGains,
+ WebRtc_Word16 bandwidth);
+
+int WebRtcIsac_DecodeLpc(Bitstr *streamdata, double *LPCCoef_lo, double *LPCCoef_hi, int *outmodel);
+
+/* quantize & code LPC Coef */
+void WebRtcIsac_EncodeLpcLb(double *LPCCoef_lo, double *LPCCoef_hi, int *model, double *size, Bitstr *streamdata, ISAC_SaveEncData_t* encData);
+void WebRtcIsac_EncodeLpcGainLb(double *LPCCoef_lo, double *LPCCoef_hi, int model, Bitstr *streamdata, ISAC_SaveEncData_t* encData);
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcUB()
+ * Encode LPC parameters, given as A-polynomial, of upper-band. The encoding
+ * is performed in LAR domain.
+ * For the upper-band, we compute and encode LPC of some sub-frames, LPC of
+ * other sub-frames are computed by linear interpolation, in LAR domain. This
+ * function performs the interpolation and returns the LPC of all sub-frames.
+ *
+ * Inputs:
+ * - lpcCoef : a buffer containing A-polynomials of sub-frames
+ * (excluding first coefficient that is 1).
+ * - bandwidth : specifies if the codec is operating at 0-12 kHz
+ * or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - interpolLPCCoeff : Decoded and interpolated LPC (A-polynomial)
+ * of all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeLpcUB(
+ double* lpcCoeff,
+ Bitstr* streamdata,
+ double* interpolLPCCoeff,
+ WebRtc_Word16 bandwidth,
+ ISACUBSaveEncDataStruct* encData);
+
+/******************************************************************************
+ * WebRtcIsac_DecodeInterpolLpcUb()
+ * Decode LPC coefficients and interpolate to get the coefficients fo all
+ * sub-frmaes.
+ *
+ * Inputs:
+ * - bandwidth : spepecifies if the codec is in 0-12 kHz or
+ * 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - percepFilterParam : Decoded and interpolated LPC (A-polynomial) of
+ * all sub-frames.
+ * If LP analysis is of order K, and there are N
+ * sub-frames then this is a buffer of size
+ * (k + 1) * N, each vector starts with the LPC gain
+ * of the corresponding sub-frame. The LPC gains
+ * are encoded and inserted after this function is
+ * called. The first A-coefficient which is 1 is not
+ * included.
+ *
+ * Return value : 0 if encoding is successful,
+ * <0 if failed to encode.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeInterpolLpcUb(
+ Bitstr* streamdata,
+ double* percepFilterParam,
+ WebRtc_Word16 bandwidth);
+
+/* decode & dequantize RC */
+int WebRtcIsac_DecodeRc(Bitstr *streamdata, WebRtc_Word16 *RCQ15);
+
+/* quantize & code RC */
+void WebRtcIsac_EncodeRc(WebRtc_Word16 *RCQ15, Bitstr *streamdata);
+
+/* decode & dequantize squared Gain */
+int WebRtcIsac_DecodeGain2(Bitstr *streamdata, WebRtc_Word32 *Gain2);
+
+/* quantize & code squared Gain (input is squared gain) */
+int WebRtcIsac_EncodeGain2(WebRtc_Word32 *gain2, Bitstr *streamdata);
+
+void WebRtcIsac_EncodePitchGain(WebRtc_Word16* PitchGains_Q12, Bitstr* streamdata, ISAC_SaveEncData_t* encData);
+
+void WebRtcIsac_EncodePitchLag(double* PitchLags, WebRtc_Word16* PitchGain_Q12, Bitstr* streamdata, ISAC_SaveEncData_t* encData);
+
+int WebRtcIsac_DecodePitchGain(Bitstr *streamdata, WebRtc_Word16 *PitchGain_Q12);
+int WebRtcIsac_DecodePitchLag(Bitstr *streamdata, WebRtc_Word16 *PitchGain_Q12, double *PitchLag);
+
+int WebRtcIsac_DecodeFrameLen(Bitstr *streamdata, WebRtc_Word16 *framelength);
+int WebRtcIsac_EncodeFrameLen(WebRtc_Word16 framelength, Bitstr *streamdata);
+int WebRtcIsac_DecodeSendBW(Bitstr *streamdata, WebRtc_Word16 *BWno);
+void WebRtcIsac_EncodeReceiveBw(int *BWno, Bitstr *streamdata);
+
+/* step-down */
+void WebRtcIsac_Poly2Rc(double *a, int N, double *RC);
+
+/* step-up */
+void WebRtcIsac_Rc2Poly(double *RC, int N, double *a);
+
+void WebRtcIsac_TranscodeLPCCoef(double *LPCCoef_lo, double *LPCCoef_hi, int model,
+ int *index_g);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Encode LPC gains of sub-Frames.
+ *
+ * Input/outputs:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded. The input values are
+ * overwritten by the quantized values.
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpcGainIndex : quantization indices for lpc gains, these will
+ * be stored to be used for FEC.
+ */
+void WebRtcIsac_EncodeLpcGainUb(
+ double* lpGains,
+ Bitstr* streamdata,
+ int* lpcGainIndex);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeLpcGainUb()
+ * Store LPC gains of sub-Frames in 'streamdata'.
+ *
+ * Input:
+ * - lpGains : a buffer which contains 'SUBFRAME' number of
+ * LP gains to be encoded.
+ * Input/outputs:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ */
+void WebRtcIsac_StoreLpcGainUb(
+ double* lpGains,
+ Bitstr* streamdata);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeLpcGainUb()
+ * Decode the LPC gain of sub-frames.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - lpGains : a buffer where decoded LPC gians will be stored.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeLpcGainUb(
+ double* lpGains,
+ Bitstr* streamdata);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeBandwidth()
+ * Encode if the bandwidth of encoded audio is 0-12 kHz or 0-16 kHz.
+ *
+ * Input:
+ * - bandwidth : an enumerator specifying if the codec in is
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeBandwidth(
+ enum ISACBandwidth bandwidth,
+ Bitstr* streamData);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeBandwidth()
+ * Decode the bandwidth of the encoded audio, i.e. if the bandwidth is 0-12 kHz
+ * or 0-16 kHz.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - bandwidth : an enumerator specifying if the codec is in
+ * 0-12 kHz or 0-16 kHz mode.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeBandwidth(
+ Bitstr* streamData,
+ enum ISACBandwidth* bandwidth);
+
+
+/******************************************************************************
+ * WebRtcIsac_EncodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Input:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_EncodeJitterInfo(
+ WebRtc_Word32 jitterIndex,
+ Bitstr* streamData);
+
+
+/******************************************************************************
+ * WebRtcIsac_DecodeJitterInfo()
+ * Decode the jitter information.
+ *
+ * Input/output:
+ * - streamdata : pointer to a stucture containg the encoded
+ * data and theparameters needed for entropy
+ * coding.
+ *
+ * Output:
+ * - jitterInfo : one bit of info specifying if the channel is
+ * in high/low jitter. Zero indicates low jitter
+ * and one indicates high jitter.
+ *
+ * Return value : 0 if succeeded.
+ * <0 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_DecodeJitterInfo(
+ Bitstr* streamData,
+ WebRtc_Word32* jitterInfo);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_ENTROPY_CODING_H_ */
diff --git a/src/mod/codecs/mod_isac/fft.c b/src/mod/codecs/mod_isac/fft.c
new file mode 100644
index 0000000000..c8247983aa
--- /dev/null
+++ b/src/mod/codecs/mod_isac/fft.c
@@ -0,0 +1,947 @@
+/*
+ * Copyright(c)1995,97 Mark Olesen
+ * Queen's Univ at Kingston (Canada)
+ *
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose without fee is hereby granted, provided that this
+ * entire notice is included in all copies of any software which is
+ * or includes a copy or modification of this software and in all
+ * copies of the supporting documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
+ * UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
+ * KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * All of which is to say that you can do what you like with this
+ * source code provided you don't try to sell it as your own and you
+ * include an unaltered copy of this message (including the
+ * copyright).
+ *
+ * It is also implicitly understood that bug fixes and improvements
+ * should make their way back to the general Internet community so
+ * that everyone benefits.
+ *
+ * Changes:
+ * Trivial type modifications by the WebRTC authors.
+ */
+
+
+/*
+ * File:
+ * WebRtcIsac_Fftn.c
+ *
+ * Public:
+ * WebRtcIsac_Fftn / fftnf ();
+ *
+ * Private:
+ * WebRtcIsac_Fftradix / fftradixf ();
+ *
+ * Descript:
+ * multivariate complex Fourier transform, computed in place
+ * using mixed-radix Fast Fourier Transform algorithm.
+ *
+ * Fortran code by:
+ * RC Singleton, Stanford Research Institute, Sept. 1968
+ *
+ * translated by f2c (version 19950721).
+ *
+ * int WebRtcIsac_Fftn (int ndim, const int dims[], REAL Re[], REAL Im[],
+ * int iSign, double scaling);
+ *
+ * NDIM = the total number dimensions
+ * DIMS = a vector of array sizes
+ * if NDIM is zero then DIMS must be zero-terminated
+ *
+ * RE and IM hold the real and imaginary components of the data, and return
+ * the resulting real and imaginary Fourier coefficients. Multidimensional
+ * data *must* be allocated contiguously. There is no limit on the number
+ * of dimensions.
+ *
+ * ISIGN = the sign of the complex exponential (ie, forward or inverse FFT)
+ * the magnitude of ISIGN (normally 1) is used to determine the
+ * correct indexing increment (see below).
+ *
+ * SCALING = normalizing constant by which the final result is *divided*
+ * if SCALING == -1, normalize by total dimension of the transform
+ * if SCALING < -1, normalize by the square-root of the total dimension
+ *
+ * example:
+ * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
+ *
+ * int dims[3] = {n1,n2,n3}
+ * WebRtcIsac_Fftn (3, dims, Re, Im, 1, scaling);
+ *
+ *-----------------------------------------------------------------------*
+ * int WebRtcIsac_Fftradix (REAL Re[], REAL Im[], size_t nTotal, size_t nPass,
+ * size_t nSpan, int iSign, size_t max_factors,
+ * size_t max_perm);
+ *
+ * RE, IM - see above documentation
+ *
+ * Although there is no limit on the number of dimensions, WebRtcIsac_Fftradix() must
+ * be called once for each dimension, but the calls may be in any order.
+ *
+ * NTOTAL = the total number of complex data values
+ * NPASS = the dimension of the current variable
+ * NSPAN/NPASS = the spacing of consecutive data values while indexing the
+ * current variable
+ * ISIGN - see above documentation
+ *
+ * example:
+ * tri-variate transform with Re[n1][n2][n3], Im[n1][n2][n3]
+ *
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n1, n1, 1, maxf, maxp);
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n2, n1*n2, 1, maxf, maxp);
+ * WebRtcIsac_Fftradix (Re, Im, n1*n2*n3, n3, n1*n2*n3, 1, maxf, maxp);
+ *
+ * single-variate transform,
+ * NTOTAL = N = NSPAN = (number of complex data values),
+ *
+ * WebRtcIsac_Fftradix (Re, Im, n, n, n, 1, maxf, maxp);
+ *
+ * The data can also be stored in a single array with alternating real and
+ * imaginary parts, the magnitude of ISIGN is changed to 2 to give correct
+ * indexing increment, and data [0] and data [1] used to pass the initial
+ * addresses for the sequences of real and imaginary values,
+ *
+ * example:
+ * REAL data [2*NTOTAL];
+ * WebRtcIsac_Fftradix ( &data[0], &data[1], NTOTAL, nPass, nSpan, 2, maxf, maxp);
+ *
+ * for temporary allocation:
+ *
+ * MAX_FACTORS >= the maximum prime factor of NPASS
+ * MAX_PERM >= the number of prime factors of NPASS. In addition,
+ * if the square-free portion K of NPASS has two or more prime
+ * factors, then MAX_PERM >= (K-1)
+ *
+ * storage in FACTOR for a maximum of 15 prime factors of NPASS. if NPASS
+ * has more than one square-free factor, the product of the square-free
+ * factors must be <= 210 array storage for maximum prime factor of 23 the
+ * following two constants should agree with the array dimensions.
+ *
+ *----------------------------------------------------------------------*/
+#include "fft.h"
+
+#include
+#include
+
+
+
+/* double precision routine */
+static int
+WebRtcIsac_Fftradix (double Re[], double Im[],
+ size_t nTotal, size_t nPass, size_t nSpan, int isign,
+ int max_factors, unsigned int max_perm,
+ FFTstr *fftstate);
+
+
+
+#ifndef M_PI
+# define M_PI 3.14159265358979323846264338327950288
+#endif
+
+#ifndef SIN60
+# define SIN60 0.86602540378443865 /* sin(60 deg) */
+# define COS72 0.30901699437494742 /* cos(72 deg) */
+# define SIN72 0.95105651629515357 /* sin(72 deg) */
+#endif
+
+# define REAL double
+# define FFTN WebRtcIsac_Fftn
+# define FFTNS "fftn"
+# define FFTRADIX WebRtcIsac_Fftradix
+# define FFTRADIXS "fftradix"
+
+
+int WebRtcIsac_Fftns(unsigned int ndim, const int dims[],
+ double Re[],
+ double Im[],
+ int iSign,
+ double scaling,
+ FFTstr *fftstate)
+{
+
+ size_t nSpan, nPass, nTotal;
+ unsigned int i;
+ int ret, max_factors, max_perm;
+
+ /*
+ * tally the number of elements in the data array
+ * and determine the number of dimensions
+ */
+ nTotal = 1;
+ if (ndim && dims [0])
+ {
+ for (i = 0; i < ndim; i++)
+ {
+ if (dims [i] <= 0)
+ {
+ return -1;
+ }
+ nTotal *= dims [i];
+ }
+ }
+ else
+ {
+ ndim = 0;
+ for (i = 0; dims [i]; i++)
+ {
+ if (dims [i] <= 0)
+ {
+ return -1;
+ }
+ nTotal *= dims [i];
+ ndim++;
+ }
+ }
+
+ /* determine maximum number of factors and permuations */
+#if 1
+ /*
+ * follow John Beale's example, just use the largest dimension and don't
+ * worry about excess allocation. May be someone else will do it?
+ */
+ max_factors = max_perm = 1;
+ for (i = 0; i < ndim; i++)
+ {
+ nSpan = dims [i];
+ if ((int)nSpan > max_factors)
+ {
+ max_factors = (int)nSpan;
+ }
+ if ((int)nSpan > max_perm)
+ {
+ max_perm = (int)nSpan;
+ }
+ }
+#else
+ /* use the constants used in the original Fortran code */
+ max_factors = 23;
+ max_perm = 209;
+#endif
+ /* loop over the dimensions: */
+ nPass = 1;
+ for (i = 0; i < ndim; i++)
+ {
+ nSpan = dims [i];
+ nPass *= nSpan;
+ ret = FFTRADIX (Re, Im, nTotal, nSpan, nPass, iSign,
+ max_factors, max_perm, fftstate);
+ /* exit, clean-up already done */
+ if (ret)
+ return ret;
+ }
+
+ /* Divide through by the normalizing constant: */
+ if (scaling && scaling != 1.0)
+ {
+ if (iSign < 0) iSign = -iSign;
+ if (scaling < 0.0)
+ {
+ scaling = (double)nTotal;
+ if (scaling < -1.0)
+ scaling = sqrt (scaling);
+ }
+ scaling = 1.0 / scaling; /* multiply is often faster */
+ for (i = 0; i < nTotal; i += iSign)
+ {
+ Re [i] *= scaling;
+ Im [i] *= scaling;
+ }
+ }
+ return 0;
+}
+
+/*
+ * singleton's mixed radix routine
+ *
+ * could move allocation out to WebRtcIsac_Fftn(), but leave it here so that it's
+ * possible to make this a standalone function
+ */
+
+static int FFTRADIX (REAL Re[],
+ REAL Im[],
+ size_t nTotal,
+ size_t nPass,
+ size_t nSpan,
+ int iSign,
+ int max_factors,
+ unsigned int max_perm,
+ FFTstr *fftstate)
+{
+ int ii, mfactor, kspan, ispan, inc;
+ int j, jc, jf, jj, k, k1, k2, k3, k4, kk, kt, nn, ns, nt;
+
+
+ REAL radf;
+ REAL c1, c2, c3, cd, aa, aj, ak, ajm, ajp, akm, akp;
+ REAL s1, s2, s3, sd, bb, bj, bk, bjm, bjp, bkm, bkp;
+
+ REAL *Rtmp = NULL; /* temp space for real part*/
+ REAL *Itmp = NULL; /* temp space for imaginary part */
+ REAL *Cos = NULL; /* Cosine values */
+ REAL *Sin = NULL; /* Sine values */
+
+ REAL s60 = SIN60; /* sin(60 deg) */
+ REAL c72 = COS72; /* cos(72 deg) */
+ REAL s72 = SIN72; /* sin(72 deg) */
+ REAL pi2 = M_PI; /* use PI first, 2 PI later */
+
+
+ fftstate->SpaceAlloced = 0;
+ fftstate->MaxPermAlloced = 0;
+
+
+ // initialize to avoid warnings
+ k3 = c2 = c3 = s2 = s3 = 0.0;
+
+ if (nPass < 2)
+ return 0;
+
+ /* allocate storage */
+ if (fftstate->SpaceAlloced < max_factors * sizeof (REAL))
+ {
+#ifdef SUN_BROKEN_REALLOC
+ if (!fftstate->SpaceAlloced) /* first time */
+ {
+ fftstate->SpaceAlloced = max_factors * sizeof (REAL);
+ }
+ else
+ {
+#endif
+ fftstate->SpaceAlloced = max_factors * sizeof (REAL);
+#ifdef SUN_BROKEN_REALLOC
+ }
+#endif
+ }
+ else
+ {
+ /* allow full use of alloc'd space */
+ max_factors = fftstate->SpaceAlloced / sizeof (REAL);
+ }
+ if (fftstate->MaxPermAlloced < max_perm)
+ {
+#ifdef SUN_BROKEN_REALLOC
+ if (!fftstate->MaxPermAlloced) /* first time */
+ else
+#endif
+ fftstate->MaxPermAlloced = max_perm;
+ }
+ else
+ {
+ /* allow full use of alloc'd space */
+ max_perm = fftstate->MaxPermAlloced;
+ }
+ if (fftstate->Tmp0 == NULL || fftstate->Tmp1 == NULL || fftstate->Tmp2 == NULL || fftstate->Tmp3 == NULL
+ || fftstate->Perm == NULL) {
+ return -1;
+ }
+
+ /* assign pointers */
+ Rtmp = (REAL *) fftstate->Tmp0;
+ Itmp = (REAL *) fftstate->Tmp1;
+ Cos = (REAL *) fftstate->Tmp2;
+ Sin = (REAL *) fftstate->Tmp3;
+
+ /*
+ * Function Body
+ */
+ inc = iSign;
+ if (iSign < 0) {
+ s72 = -s72;
+ s60 = -s60;
+ pi2 = -pi2;
+ inc = -inc; /* absolute value */
+ }
+
+ /* adjust for strange increments */
+ nt = inc * (int)nTotal;
+ ns = inc * (int)nSpan;
+ kspan = ns;
+
+ nn = nt - inc;
+ jc = ns / (int)nPass;
+ radf = pi2 * (double) jc;
+ pi2 *= 2.0; /* use 2 PI from here on */
+
+ ii = 0;
+ jf = 0;
+ /* determine the factors of n */
+ mfactor = 0;
+ k = (int)nPass;
+ while (k % 16 == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = 4;
+ k /= 16;
+ }
+ j = 3;
+ jj = 9;
+ do {
+ while (k % jj == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = j;
+ k /= jj;
+ }
+ j += 2;
+ jj = j * j;
+ } while (jj <= k);
+ if (k <= 4) {
+ kt = mfactor;
+ fftstate->factor [mfactor] = k;
+ if (k != 1)
+ mfactor++;
+ } else {
+ if (k - (k / 4 << 2) == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = 2;
+ k /= 4;
+ }
+ kt = mfactor;
+ j = 2;
+ do {
+ if (k % j == 0) {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = j;
+ k /= j;
+ }
+ j = ((j + 1) / 2 << 1) + 1;
+ } while (j <= k);
+ }
+ if (kt) {
+ j = kt;
+ do {
+ mfactor++;
+ fftstate->factor [mfactor - 1] = fftstate->factor [j - 1];
+ j--;
+ } while (j);
+ }
+
+ /* test that mfactors is in range */
+ if (mfactor > NFACTOR)
+ {
+ return -1;
+ }
+
+ /* compute fourier transform */
+ for (;;) {
+ sd = radf / (double) kspan;
+ cd = sin(sd);
+ cd = 2.0 * cd * cd;
+ sd = sin(sd + sd);
+ kk = 0;
+ ii++;
+
+ switch (fftstate->factor [ii - 1]) {
+ case 2:
+ /* transform for factor of 2 (including rotation factor) */
+ kspan /= 2;
+ k1 = kspan + 2;
+ do {
+ do {
+ k2 = kk + kspan;
+ ak = Re [k2];
+ bk = Im [k2];
+ Re [k2] = Re [kk] - ak;
+ Im [k2] = Im [kk] - bk;
+ Re [kk] += ak;
+ Im [kk] += bk;
+ kk = k2 + kspan;
+ } while (kk < nn);
+ kk -= nn;
+ } while (kk < jc);
+ if (kk >= kspan)
+ goto Permute_Results_Label; /* exit infinite loop */
+ do {
+ c1 = 1.0 - cd;
+ s1 = sd;
+ do {
+ do {
+ do {
+ k2 = kk + kspan;
+ ak = Re [kk] - Re [k2];
+ bk = Im [kk] - Im [k2];
+ Re [kk] += Re [k2];
+ Im [kk] += Im [k2];
+ Re [k2] = c1 * ak - s1 * bk;
+ Im [k2] = s1 * ak + c1 * bk;
+ kk = k2 + kspan;
+ } while (kk < (nt-1));
+ k2 = kk - nt;
+ c1 = -c1;
+ kk = k1 - k2;
+ } while (kk > k2);
+ ak = c1 - (cd * c1 + sd * s1);
+ s1 = sd * c1 - cd * s1 + s1;
+ c1 = 2.0 - (ak * ak + s1 * s1);
+ s1 *= c1;
+ c1 *= ak;
+ kk += jc;
+ } while (kk < k2);
+ k1 += inc + inc;
+ kk = (k1 - kspan + 1) / 2 + jc - 1;
+ } while (kk < (jc + jc));
+ break;
+
+ case 4: /* transform for factor of 4 */
+ ispan = kspan;
+ kspan /= 4;
+
+ do {
+ c1 = 1.0;
+ s1 = 0.0;
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ k3 = k2 + kspan;
+ akp = Re [kk] + Re [k2];
+ akm = Re [kk] - Re [k2];
+ ajp = Re [k1] + Re [k3];
+ ajm = Re [k1] - Re [k3];
+ bkp = Im [kk] + Im [k2];
+ bkm = Im [kk] - Im [k2];
+ bjp = Im [k1] + Im [k3];
+ bjm = Im [k1] - Im [k3];
+ Re [kk] = akp + ajp;
+ Im [kk] = bkp + bjp;
+ ajp = akp - ajp;
+ bjp = bkp - bjp;
+ if (iSign < 0) {
+ akp = akm + bjm;
+ bkp = bkm - ajm;
+ akm -= bjm;
+ bkm += ajm;
+ } else {
+ akp = akm - bjm;
+ bkp = bkm + ajm;
+ akm += bjm;
+ bkm -= ajm;
+ }
+ /* avoid useless multiplies */
+ if (s1 == 0.0) {
+ Re [k1] = akp;
+ Re [k2] = ajp;
+ Re [k3] = akm;
+ Im [k1] = bkp;
+ Im [k2] = bjp;
+ Im [k3] = bkm;
+ } else {
+ Re [k1] = akp * c1 - bkp * s1;
+ Re [k2] = ajp * c2 - bjp * s2;
+ Re [k3] = akm * c3 - bkm * s3;
+ Im [k1] = akp * s1 + bkp * c1;
+ Im [k2] = ajp * s2 + bjp * c2;
+ Im [k3] = akm * s3 + bkm * c3;
+ }
+ kk = k3 + kspan;
+ } while (kk < nt);
+
+ c2 = c1 - (cd * c1 + sd * s1);
+ s1 = sd * c1 - cd * s1 + s1;
+ c1 = 2.0 - (c2 * c2 + s1 * s1);
+ s1 *= c1;
+ c1 *= c2;
+ /* values of c2, c3, s2, s3 that will get used next time */
+ c2 = c1 * c1 - s1 * s1;
+ s2 = 2.0 * c1 * s1;
+ c3 = c2 * c1 - s2 * s1;
+ s3 = c2 * s1 + s2 * c1;
+ kk = kk - nt + jc;
+ } while (kk < kspan);
+ kk = kk - kspan + inc;
+ } while (kk < jc);
+ if (kspan == jc)
+ goto Permute_Results_Label; /* exit infinite loop */
+ break;
+
+ default:
+ /* transform for odd factors */
+#ifdef FFT_RADIX4
+ return -1;
+ break;
+#else /* FFT_RADIX4 */
+ k = fftstate->factor [ii - 1];
+ ispan = kspan;
+ kspan /= k;
+
+ switch (k) {
+ case 3: /* transform for factor of 3 (optional code) */
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ ak = Re [kk];
+ bk = Im [kk];
+ aj = Re [k1] + Re [k2];
+ bj = Im [k1] + Im [k2];
+ Re [kk] = ak + aj;
+ Im [kk] = bk + bj;
+ ak -= 0.5 * aj;
+ bk -= 0.5 * bj;
+ aj = (Re [k1] - Re [k2]) * s60;
+ bj = (Im [k1] - Im [k2]) * s60;
+ Re [k1] = ak - bj;
+ Re [k2] = ak + bj;
+ Im [k1] = bk + aj;
+ Im [k2] = bk - aj;
+ kk = k2 + kspan;
+ } while (kk < (nn - 1));
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+
+ case 5: /* transform for factor of 5 (optional code) */
+ c2 = c72 * c72 - s72 * s72;
+ s2 = 2.0 * c72 * s72;
+ do {
+ do {
+ k1 = kk + kspan;
+ k2 = k1 + kspan;
+ k3 = k2 + kspan;
+ k4 = k3 + kspan;
+ akp = Re [k1] + Re [k4];
+ akm = Re [k1] - Re [k4];
+ bkp = Im [k1] + Im [k4];
+ bkm = Im [k1] - Im [k4];
+ ajp = Re [k2] + Re [k3];
+ ajm = Re [k2] - Re [k3];
+ bjp = Im [k2] + Im [k3];
+ bjm = Im [k2] - Im [k3];
+ aa = Re [kk];
+ bb = Im [kk];
+ Re [kk] = aa + akp + ajp;
+ Im [kk] = bb + bkp + bjp;
+ ak = akp * c72 + ajp * c2 + aa;
+ bk = bkp * c72 + bjp * c2 + bb;
+ aj = akm * s72 + ajm * s2;
+ bj = bkm * s72 + bjm * s2;
+ Re [k1] = ak - bj;
+ Re [k4] = ak + bj;
+ Im [k1] = bk + aj;
+ Im [k4] = bk - aj;
+ ak = akp * c2 + ajp * c72 + aa;
+ bk = bkp * c2 + bjp * c72 + bb;
+ aj = akm * s2 - ajm * s72;
+ bj = bkm * s2 - bjm * s72;
+ Re [k2] = ak - bj;
+ Re [k3] = ak + bj;
+ Im [k2] = bk + aj;
+ Im [k3] = bk - aj;
+ kk = k4 + kspan;
+ } while (kk < (nn-1));
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+
+ default:
+ if (k != jf) {
+ jf = k;
+ s1 = pi2 / (double) k;
+ c1 = cos(s1);
+ s1 = sin(s1);
+ if (jf > max_factors){
+ return -1;
+ }
+ Cos [jf - 1] = 1.0;
+ Sin [jf - 1] = 0.0;
+ j = 1;
+ do {
+ Cos [j - 1] = Cos [k - 1] * c1 + Sin [k - 1] * s1;
+ Sin [j - 1] = Cos [k - 1] * s1 - Sin [k - 1] * c1;
+ k--;
+ Cos [k - 1] = Cos [j - 1];
+ Sin [k - 1] = -Sin [j - 1];
+ j++;
+ } while (j < k);
+ }
+ do {
+ do {
+ k1 = kk;
+ k2 = kk + ispan;
+ ak = aa = Re [kk];
+ bk = bb = Im [kk];
+ j = 1;
+ k1 += kspan;
+ do {
+ k2 -= kspan;
+ j++;
+ Rtmp [j - 1] = Re [k1] + Re [k2];
+ ak += Rtmp [j - 1];
+ Itmp [j - 1] = Im [k1] + Im [k2];
+ bk += Itmp [j - 1];
+ j++;
+ Rtmp [j - 1] = Re [k1] - Re [k2];
+ Itmp [j - 1] = Im [k1] - Im [k2];
+ k1 += kspan;
+ } while (k1 < k2);
+ Re [kk] = ak;
+ Im [kk] = bk;
+ k1 = kk;
+ k2 = kk + ispan;
+ j = 1;
+ do {
+ k1 += kspan;
+ k2 -= kspan;
+ jj = j;
+ ak = aa;
+ bk = bb;
+ aj = 0.0;
+ bj = 0.0;
+ k = 1;
+ do {
+ k++;
+ ak += Rtmp [k - 1] * Cos [jj - 1];
+ bk += Itmp [k - 1] * Cos [jj - 1];
+ k++;
+ aj += Rtmp [k - 1] * Sin [jj - 1];
+ bj += Itmp [k - 1] * Sin [jj - 1];
+ jj += j;
+ if (jj > jf) {
+ jj -= jf;
+ }
+ } while (k < jf);
+ k = jf - j;
+ Re [k1] = ak - bj;
+ Im [k1] = bk + aj;
+ Re [k2] = ak + bj;
+ Im [k2] = bk - aj;
+ j++;
+ } while (j < k);
+ kk += ispan;
+ } while (kk < nn);
+ kk -= nn;
+ } while (kk < kspan);
+ break;
+ }
+
+ /* multiply by rotation factor (except for factors of 2 and 4) */
+ if (ii == mfactor)
+ goto Permute_Results_Label; /* exit infinite loop */
+ kk = jc;
+ do {
+ c2 = 1.0 - cd;
+ s1 = sd;
+ do {
+ c1 = c2;
+ s2 = s1;
+ kk += kspan;
+ do {
+ do {
+ ak = Re [kk];
+ Re [kk] = c2 * ak - s2 * Im [kk];
+ Im [kk] = s2 * ak + c2 * Im [kk];
+ kk += ispan;
+ } while (kk < nt);
+ ak = s1 * s2;
+ s2 = s1 * c2 + c1 * s2;
+ c2 = c1 * c2 - ak;
+ kk = kk - nt + kspan;
+ } while (kk < ispan);
+ c2 = c1 - (cd * c1 + sd * s1);
+ s1 += sd * c1 - cd * s1;
+ c1 = 2.0 - (c2 * c2 + s1 * s1);
+ s1 *= c1;
+ c2 *= c1;
+ kk = kk - ispan + jc;
+ } while (kk < kspan);
+ kk = kk - kspan + jc + inc;
+ } while (kk < (jc + jc));
+ break;
+#endif /* FFT_RADIX4 */
+ }
+ }
+
+ /* permute the results to normal order---done in two stages */
+ /* permutation for square factors of n */
+Permute_Results_Label:
+ fftstate->Perm [0] = ns;
+ if (kt) {
+ k = kt + kt + 1;
+ if (mfactor < k)
+ k--;
+ j = 1;
+ fftstate->Perm [k] = jc;
+ do {
+ fftstate->Perm [j] = fftstate->Perm [j - 1] / fftstate->factor [j - 1];
+ fftstate->Perm [k - 1] = fftstate->Perm [k] * fftstate->factor [j - 1];
+ j++;
+ k--;
+ } while (j < k);
+ k3 = fftstate->Perm [k];
+ kspan = fftstate->Perm [1];
+ kk = jc;
+ k2 = kspan;
+ j = 1;
+ if (nPass != nTotal) {
+ /* permutation for multivariate transform */
+ Permute_Multi_Label:
+ do {
+ do {
+ k = kk + jc;
+ do {
+ /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
+ ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
+ bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
+ kk += inc;
+ k2 += inc;
+ } while (kk < (k-1));
+ kk += ns - jc;
+ k2 += ns - jc;
+ } while (kk < (nt-1));
+ k2 = k2 - nt + kspan;
+ kk = kk - nt + jc;
+ } while (k2 < (ns-1));
+ do {
+ do {
+ k2 -= fftstate->Perm [j - 1];
+ j++;
+ k2 = fftstate->Perm [j] + k2;
+ } while (k2 > fftstate->Perm [j - 1]);
+ j = 1;
+ do {
+ if (kk < (k2-1))
+ goto Permute_Multi_Label;
+ kk += jc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ } while (kk < (ns-1));
+ } else {
+ /* permutation for single-variate transform (optional code) */
+ Permute_Single_Label:
+ do {
+ /* swap Re [kk] <> Re [k2], Im [kk] <> Im [k2] */
+ ak = Re [kk]; Re [kk] = Re [k2]; Re [k2] = ak;
+ bk = Im [kk]; Im [kk] = Im [k2]; Im [k2] = bk;
+ kk += inc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ do {
+ do {
+ k2 -= fftstate->Perm [j - 1];
+ j++;
+ k2 = fftstate->Perm [j] + k2;
+ } while (k2 >= fftstate->Perm [j - 1]);
+ j = 1;
+ do {
+ if (kk < k2)
+ goto Permute_Single_Label;
+ kk += inc;
+ k2 += kspan;
+ } while (k2 < (ns-1));
+ } while (kk < (ns-1));
+ }
+ jc = k3;
+ }
+
+ if ((kt << 1) + 1 >= mfactor)
+ return 0;
+ ispan = fftstate->Perm [kt];
+ /* permutation for square-free factors of n */
+ j = mfactor - kt;
+ fftstate->factor [j] = 1;
+ do {
+ fftstate->factor [j - 1] *= fftstate->factor [j];
+ j--;
+ } while (j != kt);
+ kt++;
+ nn = fftstate->factor [kt - 1] - 1;
+ if (nn > (int) max_perm) {
+ return -1;
+ }
+ j = jj = 0;
+ for (;;) {
+ k = kt + 1;
+ k2 = fftstate->factor [kt - 1];
+ kk = fftstate->factor [k - 1];
+ j++;
+ if (j > nn)
+ break; /* exit infinite loop */
+ jj += kk;
+ while (jj >= k2) {
+ jj -= k2;
+ k2 = kk;
+ k++;
+ kk = fftstate->factor [k - 1];
+ jj += kk;
+ }
+ fftstate->Perm [j - 1] = jj;
+ }
+ /* determine the permutation cycles of length greater than 1 */
+ j = 0;
+ for (;;) {
+ do {
+ j++;
+ kk = fftstate->Perm [j - 1];
+ } while (kk < 0);
+ if (kk != j) {
+ do {
+ k = kk;
+ kk = fftstate->Perm [k - 1];
+ fftstate->Perm [k - 1] = -kk;
+ } while (kk != j);
+ k3 = kk;
+ } else {
+ fftstate->Perm [j - 1] = -j;
+ if (j == nn)
+ break; /* exit infinite loop */
+ }
+ }
+ max_factors *= inc;
+ /* reorder a and b, following the permutation cycles */
+ for (;;) {
+ j = k3 + 1;
+ nt -= ispan;
+ ii = nt - inc + 1;
+ if (nt < 0)
+ break; /* exit infinite loop */
+ do {
+ do {
+ j--;
+ } while (fftstate->Perm [j - 1] < 0);
+ jj = jc;
+ do {
+ kspan = jj;
+ if (jj > max_factors) {
+ kspan = max_factors;
+ }
+ jj -= kspan;
+ k = fftstate->Perm [j - 1];
+ kk = jc * k + ii + jj;
+ k1 = kk + kspan - 1;
+ k2 = 0;
+ do {
+ k2++;
+ Rtmp [k2 - 1] = Re [k1];
+ Itmp [k2 - 1] = Im [k1];
+ k1 -= inc;
+ } while (k1 != (kk-1));
+ do {
+ k1 = kk + kspan - 1;
+ k2 = k1 - jc * (k + fftstate->Perm [k - 1]);
+ k = -fftstate->Perm [k - 1];
+ do {
+ Re [k1] = Re [k2];
+ Im [k1] = Im [k2];
+ k1 -= inc;
+ k2 -= inc;
+ } while (k1 != (kk-1));
+ kk = k2 + 1;
+ } while (k != j);
+ k1 = kk + kspan - 1;
+ k2 = 0;
+ do {
+ k2++;
+ Re [k1] = Rtmp [k2 - 1];
+ Im [k1] = Itmp [k2 - 1];
+ k1 -= inc;
+ } while (k1 != (kk-1));
+ } while (jj);
+ } while (j != 1);
+ }
+ return 0; /* exit point here */
+}
+/* ---------------------- end-of-file (c source) ---------------------- */
+
diff --git a/src/mod/codecs/mod_isac/fft.h b/src/mod/codecs/mod_isac/fft.h
new file mode 100644
index 0000000000..a42f57bcb5
--- /dev/null
+++ b/src/mod/codecs/mod_isac/fft.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*--------------------------------*-C-*---------------------------------*
+ * File:
+ * fftn.h
+ * ---------------------------------------------------------------------*
+ * Re[]: real value array
+ * Im[]: imaginary value array
+ * nTotal: total number of complex values
+ * nPass: number of elements involved in this pass of transform
+ * nSpan: nspan/nPass = number of bytes to increment pointer
+ * in Re[] and Im[]
+ * isign: exponent: +1 = forward -1 = reverse
+ * scaling: normalizing constant by which the final result is *divided*
+ * scaling == -1, normalize by total dimension of the transform
+ * scaling < -1, normalize by the square-root of the total dimension
+ *
+ * ----------------------------------------------------------------------
+ * See the comments in the code for correct usage!
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
+
+
+#include "structs.h"
+
+
+/* double precision routine */
+
+
+int WebRtcIsac_Fftns (unsigned int ndim, const int dims[], double Re[], double Im[],
+ int isign, double scaling, FFTstr *fftstate);
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_ */
diff --git a/src/mod/codecs/mod_isac/filter_ar.c b/src/mod/codecs/mod_isac/filter_ar.c
new file mode 100644
index 0000000000..24e83a6b91
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filter_ar.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_FilterAR().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* a,
+ int a_length,
+ G_CONST WebRtc_Word16* x,
+ int x_length,
+ WebRtc_Word16* state,
+ int state_length,
+ WebRtc_Word16* state_low,
+ int state_low_length,
+ WebRtc_Word16* filtered,
+ WebRtc_Word16* filtered_low,
+ int filtered_low_length)
+{
+ WebRtc_Word32 o;
+ WebRtc_Word32 oLOW;
+ int i, j, stop;
+ G_CONST WebRtc_Word16* x_ptr = &x[0];
+ WebRtc_Word16* filteredFINAL_ptr = filtered;
+ WebRtc_Word16* filteredFINAL_LOW_ptr = filtered_low;
+
+ for (i = 0; i < x_length; i++)
+ {
+ // Calculate filtered[i] and filtered_low[i]
+ G_CONST WebRtc_Word16* a_ptr = &a[1];
+ WebRtc_Word16* filtered_ptr = &filtered[i - 1];
+ WebRtc_Word16* filtered_low_ptr = &filtered_low[i - 1];
+ WebRtc_Word16* state_ptr = &state[state_length - 1];
+ WebRtc_Word16* state_low_ptr = &state_low[state_length - 1];
+
+ o = (WebRtc_Word32)(*x_ptr++) << 12;
+ oLOW = (WebRtc_Word32)0;
+
+ stop = (i < a_length) ? i + 1 : a_length;
+ for (j = 1; j < stop; j++)
+ {
+ o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *filtered_ptr--);
+ oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *filtered_low_ptr--);
+ }
+ for (j = i + 1; j < a_length; j++)
+ {
+ o -= WEBRTC_SPL_MUL_16_16(*a_ptr, *state_ptr--);
+ oLOW -= WEBRTC_SPL_MUL_16_16(*a_ptr++, *state_low_ptr--);
+ }
+
+ o += (oLOW >> 12);
+ *filteredFINAL_ptr = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);
+ *filteredFINAL_LOW_ptr++ = (WebRtc_Word16)(o - ((WebRtc_Word32)(*filteredFINAL_ptr++)
+ << 12));
+ }
+
+ // Save the filter state
+ if (x_length >= state_length)
+ {
+ WebRtcSpl_CopyFromEndW16(filtered, x_length, a_length - 1, state);
+ WebRtcSpl_CopyFromEndW16(filtered_low, x_length, a_length - 1, state_low);
+ } else
+ {
+ for (i = 0; i < state_length - x_length; i++)
+ {
+ state[i] = state[i + x_length];
+ state_low[i] = state_low[i + x_length];
+ }
+ for (i = 0; i < x_length; i++)
+ {
+ state[state_length - x_length + i] = filtered[i];
+ state[state_length - x_length + i] = filtered_low[i];
+ }
+ }
+
+ return x_length;
+}
diff --git a/src/mod/codecs/mod_isac/filter_ar_fast_q12.c b/src/mod/codecs/mod_isac/filter_ar_fast_q12.c
new file mode 100644
index 0000000000..6184da3f4c
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filter_ar_fast_q12.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_FilterARFastQ12().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_FilterARFastQ12(WebRtc_Word16 *in, WebRtc_Word16 *out, WebRtc_Word16 *A,
+ WebRtc_Word16 A_length, WebRtc_Word16 length)
+{
+ WebRtc_Word32 o;
+ int i, j;
+
+ WebRtc_Word16 *x_ptr = &in[0];
+ WebRtc_Word16 *filtered_ptr = &out[0];
+
+ for (i = 0; i < length; i++)
+ {
+ // Calculate filtered[i]
+ G_CONST WebRtc_Word16 *a_ptr = &A[0];
+ WebRtc_Word16 *state_ptr = &out[i - 1];
+
+ o = WEBRTC_SPL_MUL_16_16(*x_ptr++, *a_ptr++);
+
+ for (j = 1; j < A_length; j++)
+ {
+ o -= WEBRTC_SPL_MUL_16_16(*a_ptr++,*state_ptr--);
+ }
+
+ // Saturate the output
+ o = WEBRTC_SPL_SAT((WebRtc_Word32)134215679, o, (WebRtc_Word32)-134217728);
+
+ *filtered_ptr++ = (WebRtc_Word16)((o + (WebRtc_Word32)2048) >> 12);
+ }
+
+ return;
+}
diff --git a/src/mod/codecs/mod_isac/filter_functions.c b/src/mod/codecs/mod_isac/filter_functions.c
new file mode 100644
index 0000000000..33024a3dee
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filter_functions.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include
+#ifdef WEBRTC_ANDROID
+#include
+#endif
+#include "pitch_estimator.h"
+#include "lpc_analysis.h"
+#include "codec.h"
+
+
+
+void WebRtcIsac_AllPoleFilter(double *InOut, double *Coef, int lengthInOut, int orderCoef){
+
+ /* the state of filter is assumed to be in InOut[-1] to InOut[-orderCoef] */
+ double scal;
+ double sum;
+ int n,k;
+
+ //if (fabs(Coef[0]-1.0)<0.001) {
+ if ( (Coef[0] > 0.9999) && (Coef[0] < 1.0001) )
+ {
+ for(n = 0; n < lengthInOut; n++)
+ {
+ sum = Coef[1] * InOut[-1];
+ for(k = 2; k <= orderCoef; k++){
+ sum += Coef[k] * InOut[-k];
+ }
+ *InOut++ -= sum;
+ }
+ }
+ else
+ {
+ scal = 1.0 / Coef[0];
+ for(n=0;nbuffer, sizeof(double) * PITCH_WLPCBUFLEN);
+ memcpy(tmpbuffer+PITCH_WLPCBUFLEN, in, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(wfdata->buffer, tmpbuffer+PITCH_FRAME_LEN, sizeof(double) * PITCH_WLPCBUFLEN);
+
+ dp=weoutbuf;
+ dp2=whoutbuf;
+ for (k=0;kweostate[k];
+ *dp2++ = wfdata->whostate[k];
+ opol[k]=0.0;
+ }
+ opol[0]=1.0;
+ opol[PITCH_WLPCORDER]=0.0;
+ weo=dp;
+ who=dp2;
+
+ endpos=PITCH_WLPCBUFLEN + PITCH_SUBFRAME_LEN;
+ inp=tmpbuffer + PITCH_WLPCBUFLEN;
+
+ for (n=0; nwindow[k]*tmpbuffer[start+k];
+ }
+
+ /* Get LPC polynomial */
+ WebRtcIsac_AutoCorr(corr, ext, PITCH_WLPCWINLEN, PITCH_WLPCORDER);
+ corr[0]=1.01*corr[0]+1.0; /* White noise correction */
+ WebRtcIsac_LevDurb(apol, rc, corr, PITCH_WLPCORDER);
+ WebRtcIsac_BwExpand(apolr, apol, rho, PITCH_WLPCORDER+1);
+
+ /* Filtering */
+ WebRtcIsac_ZeroPoleFilter(inp, apol, apolr, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, weo);
+ WebRtcIsac_ZeroPoleFilter(inp, apolr, opol, PITCH_SUBFRAME_LEN, PITCH_WLPCORDER, who);
+
+ inp+=PITCH_SUBFRAME_LEN;
+ endpos+=PITCH_SUBFRAME_LEN;
+ weo+=PITCH_SUBFRAME_LEN;
+ who+=PITCH_SUBFRAME_LEN;
+ }
+
+ /* Export filter states */
+ for (k=0;kweostate[k]=weoutbuf[PITCH_FRAME_LEN+k];
+ wfdata->whostate[k]=whoutbuf[PITCH_FRAME_LEN+k];
+ }
+
+ /* Export output data */
+ memcpy(weiout, weoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+ memcpy(whiout, whoutbuf+PITCH_WLPCORDER, sizeof(double) * PITCH_FRAME_LEN);
+}
+
+
+static const double APupper[ALLPASSSECTIONS] = {0.0347, 0.3826};
+static const double APlower[ALLPASSSECTIONS] = {0.1544, 0.744};
+
+
+
+void WebRtcIsac_AllpassFilterForDec(double *InOut,
+ const double *APSectionFactors,
+ int lengthInOut,
+ double *FilterState)
+{
+ //This performs all-pass filtering--a series of first order all-pass sections are used
+ //to filter the input in a cascade manner.
+ int n,j;
+ double temp;
+ for (j=0; j> 12);
+ }
+ return;
+}
diff --git a/src/mod/codecs/mod_isac/filterbank_tables.c b/src/mod/codecs/mod_isac/filterbank_tables.c
new file mode 100644
index 0000000000..0f844af9d2
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filterbank_tables.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* filterbank_tables.c*/
+/* This file contains variables that are used in filterbanks.c*/
+
+#include "filterbank_tables.h"
+#include "settings.h"
+
+/* The composite all-pass filter factors */
+const float WebRtcIsac_kCompositeApFactorsFloat[4] = {
+ 0.03470000000000f, 0.15440000000000f, 0.38260000000000f, 0.74400000000000f};
+
+/* The upper channel all-pass filter factors */
+const float WebRtcIsac_kUpperApFactorsFloat[2] = {
+ 0.03470000000000f, 0.38260000000000f};
+
+/* The lower channel all-pass filter factors */
+const float WebRtcIsac_kLowerApFactorsFloat[2] = {
+ 0.15440000000000f, 0.74400000000000f};
+
+/* The matrix for transforming the backward composite state to upper channel state */
+const float WebRtcIsac_kTransform1Float[8] = {
+ -0.00158678506084f, 0.00127157815343f, -0.00104805672709f, 0.00084837248079f,
+ 0.00134467983258f, -0.00107756549387f, 0.00088814793277f, -0.00071893072525f};
+
+/* The matrix for transforming the backward composite state to lower channel state */
+const float WebRtcIsac_kTransform2Float[8] = {
+ -0.00170686041697f, 0.00136780109829f, -0.00112736532350f, 0.00091257055385f,
+ 0.00103094281812f, -0.00082615076557f, 0.00068092756088f, -0.00055119165484f};
diff --git a/src/mod/codecs/mod_isac/filterbank_tables.h b/src/mod/codecs/mod_isac/filterbank_tables.h
new file mode 100644
index 0000000000..e8fda5e545
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filterbank_tables.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbank_tables.h
+ *
+ * Header file for variables that are defined in
+ * filterbank_tables.c.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_
+
+#include "structs.h"
+
+/********************* Coefficient Tables ************************/
+/* The number of composite all-pass filter factors */
+#define NUMBEROFCOMPOSITEAPSECTIONS 4
+
+/* The number of all-pass filter factors in an upper or lower channel*/
+#define NUMBEROFCHANNELAPSECTIONS 2
+
+/* The composite all-pass filter factors */
+extern const float WebRtcIsac_kCompositeApFactorsFloat[4];
+
+/* The upper channel all-pass filter factors */
+extern const float WebRtcIsac_kUpperApFactorsFloat[2];
+
+/* The lower channel all-pass filter factors */
+extern const float WebRtcIsac_kLowerApFactorsFloat[2];
+
+/* The matrix for transforming the backward composite state to upper channel state */
+extern const float WebRtcIsac_kTransform1Float[8];
+
+/* The matrix for transforming the backward composite state to lower channel state */
+extern const float WebRtcIsac_kTransform2Float[8];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FILTERBANK_TABLES_H_ */
diff --git a/src/mod/codecs/mod_isac/filterbanks.c b/src/mod/codecs/mod_isac/filterbanks.c
new file mode 100644
index 0000000000..671fd321ce
--- /dev/null
+++ b/src/mod/codecs/mod_isac/filterbanks.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * filterbanks.c
+ *
+ * This file contains function WebRtcIsac_AllPassFilter2Float,
+ * WebRtcIsac_SplitAndFilter, and WebRtcIsac_FilterAndCombine
+ * which implement filterbanks that produce decimated lowpass and
+ * highpass versions of a signal, and performs reconstruction.
+ *
+ */
+
+#include "settings.h"
+#include "filterbank_tables.h"
+#include "codec.h"
+
+/* This function performs all-pass filtering--a series of first order all-pass
+ * sections are used to filter the input in a cascade manner.
+ * The input is overwritten!!
+ */
+static void WebRtcIsac_AllPassFilter2Float(float *InOut, const float *APSectionFactors,
+ int lengthInOut, int NumberOfSections,
+ float *FilterState)
+{
+ int n, j;
+ float temp;
+ for (j=0; jINLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+ HP: a FRAMESAMPLES_HALF array of high-pass filtered samples that
+ have been phase equalized. The first QLOOKAHEAD samples are
+ based on the samples in the two prefiltdata->INLABUFx arrays
+ each of length QLOOKAHEAD.
+ The remaining FRAMESAMPLES_HALF-QLOOKAHEAD samples are based
+ on the first FRAMESAMPLES_HALF-QLOOKAHEAD samples of the input
+ array in[].
+
+ LP_la: a FRAMESAMPLES_HALF array of low-pass filtered samples.
+ These samples are not phase equalized. They are computed
+ from the samples in the in[] array.
+ HP_la: a FRAMESAMPLES_HALF array of high-pass filtered samples
+ that are not phase equalized. They are computed from
+ the in[] vector.
+ prefiltdata: this input data structure's filterbank state and
+ lookahead sample buffers are updated for the next
+ encoding iteration.
+*/
+void WebRtcIsac_SplitAndFilterFloat(float *pin, float *LP, float *HP,
+ double *LP_la, double *HP_la,
+ PreFiltBankstr *prefiltdata)
+{
+ int k,n;
+ float CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState[NUMBEROFCOMPOSITEAPSECTIONS];
+ float ForTransform_CompositeAPFilterState2[NUMBEROFCOMPOSITEAPSECTIONS];
+ float tempinoutvec[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch1[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float tempin_ch2[FRAMESAMPLES+MAX_AR_MODEL_ORDER];
+ float in[FRAMESAMPLES];
+ float ftmp;
+
+
+ /* High pass filter */
+
+ for (k=0;kHPstates_float[0] +
+ kHpStCoefInFloat[3] * prefiltdata->HPstates_float[1];
+ ftmp = pin[k] - kHpStCoefInFloat[0] * prefiltdata->HPstates_float[0] -
+ kHpStCoefInFloat[1] * prefiltdata->HPstates_float[1];
+ prefiltdata->HPstates_float[1] = prefiltdata->HPstates_float[0];
+ prefiltdata->HPstates_float[0] = ftmp;
+ }
+
+ /*
+ % backwards all-pass filtering to obtain zero-phase
+ [tmp1(N2+LA:-1:LA+1, 1), state1] = filter(Q.coef, Q.coef(end:-1:1), in(N:-2:2));
+ tmp1(LA:-1:1) = filter(Q.coef, Q.coef(end:-1:1), Q.LookAheadBuf1, state1);
+ Q.LookAheadBuf1 = in(N:-2:N-2*LA+2);
+ */
+ /*Backwards all-pass filter the odd samples of the input (upper channel)
+ to eventually obtain zero phase. The composite all-pass filter (comprised of both
+ the upper and lower channel all-pass filsters in series) is used for the
+ filtering. */
+
+ /* First Channel */
+
+ /*initial state of composite filter is zero */
+ for (k=0;kINLABUF1_float,
+ WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,
+ NUMBEROFCOMPOSITEAPSECTIONS, CompositeAPFilterState);
+
+ /* save the output, but write it in forward order */
+ /* write the lookahead samples for the next encoding iteration. Every other
+ sample at the end of the input frame is written in reverse order for the
+ lookahead length. Exported in the prefiltdata structure. */
+ for (k=0;kINLABUF1_float[k];
+ prefiltdata->INLABUF1_float[k]=in[FRAMESAMPLES-1-2*k];
+ }
+
+ /* Second Channel. This is exactly like the first channel, except that the
+ even samples are now filtered instead (lower channel). */
+ for (k=0;kINLABUF2_float,
+ WebRtcIsac_kCompositeApFactorsFloat, QLOOKAHEAD,NUMBEROFCOMPOSITEAPSECTIONS,
+ CompositeAPFilterState);
+
+ for (k=0;kINLABUF2_float[k];
+ prefiltdata->INLABUF2_float[k]=in[FRAMESAMPLES-2-2*k];
+ }
+
+ /* Transform filter states from backward to forward */
+ /*At this point, each of the states of the backwards composite filters for the
+ two channels are transformed into forward filtering states for the corresponding
+ forward channel filters. Each channel's forward filtering state from the previous
+ encoding iteration is added to the transformed state to get a proper forward state */
+
+ /* So the existing NUMBEROFCOMPOSITEAPSECTIONS x 1 (4x1) state vector is multiplied by a
+ NUMBEROFCHANNELAPSECTIONSxNUMBEROFCOMPOSITEAPSECTIONS (2x4) transform matrix to get the
+ new state that is added to the previous 2x1 input state */
+
+ for (k=0;kINSTAT1_float[k] += ForTransform_CompositeAPFilterState[n]*
+ WebRtcIsac_kTransform1Float[k*NUMBEROFCHANNELAPSECTIONS+n];
+ prefiltdata->INSTAT2_float[k] += ForTransform_CompositeAPFilterState2[n]*
+ WebRtcIsac_kTransform2Float[k*NUMBEROFCHANNELAPSECTIONS+n];
+ }
+ }
+
+ /*obtain polyphase components by forward all-pass filtering through each channel */
+ /* the backward filtered samples are now forward filtered with the corresponding channel filters */
+ /* The all pass filtering automatically updates the filter states which are exported in the
+ prefiltdata structure */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch1,WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTAT2_float);
+
+ /* Now Construct low-pass and high-pass signals as combinations of polyphase components */
+ for (k=0; kINSTATLA1_float);
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2,WebRtcIsac_kLowerApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS, prefiltdata->INSTATLA2_float);
+
+ for (k=0; kSTATE_0_UPPER_float);
+
+ /* Now, all-pass filter the new lower channel signal. But since all-pass filter factors
+ at the decoder are swapped from the ones at the encoder, the 'upper' channel
+ all-pass filter factors (WebRtcIsac_kUpperApFactorsFloat) are used to filter this new
+ lower channel signal */
+ WebRtcIsac_AllPassFilter2Float(tempin_ch2, WebRtcIsac_kUpperApFactorsFloat,
+ FRAMESAMPLES_HALF, NUMBEROFCHANNELAPSECTIONS,postfiltdata->STATE_0_LOWER_float);
+
+
+ /* Merge outputs to form the full length output signal.*/
+ for (k=0;kHPstates1_float[0] +
+ kHpStCoefOut1Float[3] * postfiltdata->HPstates1_float[1];
+ ftmp = Out[k] - kHpStCoefOut1Float[0] * postfiltdata->HPstates1_float[0] -
+ kHpStCoefOut1Float[1] * postfiltdata->HPstates1_float[1];
+ postfiltdata->HPstates1_float[1] = postfiltdata->HPstates1_float[0];
+ postfiltdata->HPstates1_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+
+ for (k=0;kHPstates2_float[0] +
+ kHpStCoefOut2Float[3] * postfiltdata->HPstates2_float[1];
+ ftmp = Out[k] - kHpStCoefOut2Float[0] * postfiltdata->HPstates2_float[0] -
+ kHpStCoefOut2Float[1] * postfiltdata->HPstates2_float[1];
+ postfiltdata->HPstates2_float[1] = postfiltdata->HPstates2_float[0];
+ postfiltdata->HPstates2_float[0] = ftmp;
+ Out[k] = ftmp2;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/get_hanning_window.c b/src/mod/codecs/mod_isac/get_hanning_window.c
new file mode 100644
index 0000000000..6d67e60f7a
--- /dev/null
+++ b/src/mod/codecs/mod_isac/get_hanning_window.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_GetHanningWindow().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// Hanning table with 256 entries
+static const WebRtc_Word16 kHanningTable[] = {
+ 1, 2, 6, 10, 15, 22, 30, 39,
+ 50, 62, 75, 89, 104, 121, 138, 157,
+ 178, 199, 222, 246, 271, 297, 324, 353,
+ 383, 413, 446, 479, 513, 549, 586, 624,
+ 663, 703, 744, 787, 830, 875, 920, 967,
+ 1015, 1064, 1114, 1165, 1218, 1271, 1325, 1381,
+ 1437, 1494, 1553, 1612, 1673, 1734, 1796, 1859,
+ 1924, 1989, 2055, 2122, 2190, 2259, 2329, 2399,
+ 2471, 2543, 2617, 2691, 2765, 2841, 2918, 2995,
+ 3073, 3152, 3232, 3312, 3393, 3475, 3558, 3641,
+ 3725, 3809, 3895, 3980, 4067, 4154, 4242, 4330,
+ 4419, 4509, 4599, 4689, 4781, 4872, 4964, 5057,
+ 5150, 5244, 5338, 5432, 5527, 5622, 5718, 5814,
+ 5910, 6007, 6104, 6202, 6299, 6397, 6495, 6594,
+ 6693, 6791, 6891, 6990, 7090, 7189, 7289, 7389,
+ 7489, 7589, 7690, 7790, 7890, 7991, 8091, 8192,
+ 8293, 8393, 8494, 8594, 8694, 8795, 8895, 8995,
+ 9095, 9195, 9294, 9394, 9493, 9593, 9691, 9790,
+ 9889, 9987, 10085, 10182, 10280, 10377, 10474, 10570,
+10666, 10762, 10857, 10952, 11046, 11140, 11234, 11327,
+11420, 11512, 11603, 11695, 11785, 11875, 11965, 12054,
+12142, 12230, 12317, 12404, 12489, 12575, 12659, 12743,
+12826, 12909, 12991, 13072, 13152, 13232, 13311, 13389,
+13466, 13543, 13619, 13693, 13767, 13841, 13913, 13985,
+14055, 14125, 14194, 14262, 14329, 14395, 14460, 14525,
+14588, 14650, 14711, 14772, 14831, 14890, 14947, 15003,
+15059, 15113, 15166, 15219, 15270, 15320, 15369, 15417,
+15464, 15509, 15554, 15597, 15640, 15681, 15721, 15760,
+15798, 15835, 15871, 15905, 15938, 15971, 16001, 16031,
+16060, 16087, 16113, 16138, 16162, 16185, 16206, 16227,
+16246, 16263, 16280, 16295, 16309, 16322, 16334, 16345,
+16354, 16362, 16369, 16374, 16378, 16382, 16383, 16384
+};
+
+void WebRtcSpl_GetHanningWindow(WebRtc_Word16 *v, WebRtc_Word16 size)
+{
+ int jj;
+ WebRtc_Word16 *vptr1;
+
+ WebRtc_Word32 index;
+ WebRtc_Word32 factor = ((WebRtc_Word32)0x40000000);
+
+ factor = WebRtcSpl_DivW32W16(factor, size);
+ if (size < 513)
+ index = (WebRtc_Word32)-0x200000;
+ else
+ index = (WebRtc_Word32)-0x100000;
+ vptr1 = v;
+
+ for (jj = 0; jj < size; jj++)
+ {
+ index += factor;
+ (*vptr1++) = kHanningTable[index >> 22];
+ }
+
+}
diff --git a/src/mod/codecs/mod_isac/get_scaling_square.c b/src/mod/codecs/mod_isac/get_scaling_square.c
new file mode 100644
index 0000000000..dccbf334fd
--- /dev/null
+++ b/src/mod/codecs/mod_isac/get_scaling_square.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_GetScalingSquare().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+int WebRtcSpl_GetScalingSquare(WebRtc_Word16 *in_vector, int in_vector_length, int times)
+{
+ int nbits = WebRtcSpl_GetSizeInBits(times);
+ int i;
+ WebRtc_Word16 smax = -1;
+ WebRtc_Word16 sabs;
+ WebRtc_Word16 *sptr = in_vector;
+ int t;
+ int looptimes = in_vector_length;
+
+ for (i = looptimes; i > 0; i--)
+ {
+ sabs = (*sptr > 0 ? *sptr++ : -*sptr++);
+ smax = (sabs > smax ? sabs : smax);
+ }
+ t = WebRtcSpl_NormW32(WEBRTC_SPL_MUL(smax, smax));
+
+ if (smax == 0)
+ {
+ return 0; // Since norm(0) returns 0
+ } else
+ {
+ return (t > nbits) ? 0 : nbits - t;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/ilbc_specific_functions.c b/src/mod/codecs/mod_isac/ilbc_specific_functions.c
new file mode 100644
index 0000000000..5a9e5773b3
--- /dev/null
+++ b/src/mod/codecs/mod_isac/ilbc_specific_functions.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains implementations of the iLBC specific functions
+ * WebRtcSpl_ScaleAndAddVectorsWithRound()
+ * WebRtcSpl_ReverseOrderMultArrayElements()
+ * WebRtcSpl_ElementwiseVectorMult()
+ * WebRtcSpl_AddVectorsAndShift()
+ * WebRtcSpl_AddAffineVectorToVector()
+ * WebRtcSpl_AffineTransformVector()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_ScaleAndAddVectorsWithRound(WebRtc_Word16 *vector1, WebRtc_Word16 scale1,
+ WebRtc_Word16 *vector2, WebRtc_Word16 scale2,
+ WebRtc_Word16 right_shifts, WebRtc_Word16 *out,
+ WebRtc_Word16 vector_length)
+{
+ int i;
+ WebRtc_Word16 roundVal;
+ roundVal = 1 << right_shifts;
+ roundVal = roundVal >> 1;
+ for (i = 0; i < vector_length; i++)
+ {
+ out[i] = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16(vector1[i], scale1)
+ + WEBRTC_SPL_MUL_16_16(vector2[i], scale2) + roundVal) >> right_shifts);
+ }
+}
+
+void WebRtcSpl_ReverseOrderMultArrayElements(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in,
+ G_CONST WebRtc_Word16 *win,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *inptr = in;
+ G_CONST WebRtc_Word16 *winptr = win;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++,
+ *winptr--, right_shifts);
+ }
+}
+
+void WebRtcSpl_ElementwiseVectorMult(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in,
+ G_CONST WebRtc_Word16 *win, WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *inptr = in;
+ G_CONST WebRtc_Word16 *winptr = win;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++,
+ *winptr++, right_shifts);
+ }
+}
+
+void WebRtcSpl_AddVectorsAndShift(WebRtc_Word16 *out, G_CONST WebRtc_Word16 *in1,
+ G_CONST WebRtc_Word16 *in2, WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+ WebRtc_Word16 *outptr = out;
+ G_CONST WebRtc_Word16 *in1ptr = in1;
+ G_CONST WebRtc_Word16 *in2ptr = in2;
+ for (i = vector_length; i > 0; i--)
+ {
+ (*outptr++) = (WebRtc_Word16)(((*in1ptr++) + (*in2ptr++)) >> right_shifts);
+ }
+}
+
+void WebRtcSpl_AddAffineVectorToVector(WebRtc_Word16 *out, WebRtc_Word16 *in,
+ WebRtc_Word16 gain, WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts, int vector_length)
+{
+ WebRtc_Word16 *inPtr;
+ WebRtc_Word16 *outPtr;
+ int i;
+
+ inPtr = in;
+ outPtr = out;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outPtr++) += (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16((*inPtr++), gain)
+ + (WebRtc_Word32)add_constant) >> right_shifts);
+ }
+}
+
+void WebRtcSpl_AffineTransformVector(WebRtc_Word16 *out, WebRtc_Word16 *in,
+ WebRtc_Word16 gain, WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts, int vector_length)
+{
+ WebRtc_Word16 *inPtr;
+ WebRtc_Word16 *outPtr;
+ int i;
+
+ inPtr = in;
+ outPtr = out;
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outPtr++) = (WebRtc_Word16)((WEBRTC_SPL_MUL_16_16((*inPtr++), gain)
+ + (WebRtc_Word32)add_constant) >> right_shifts);
+ }
+}
diff --git a/src/mod/codecs/mod_isac/intialize.c b/src/mod/codecs/mod_isac/intialize.c
new file mode 100644
index 0000000000..6df034d1c7
--- /dev/null
+++ b/src/mod/codecs/mod_isac/intialize.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* encode.c - Encoding function for the iSAC coder */
+
+#include "structs.h"
+#include "codec.h"
+#include "pitch_estimator.h"
+
+#include
+
+void WebRtcIsac_InitMasking(MaskFiltstr *maskdata) {
+
+ int k;
+
+ for (k = 0; k < WINLEN; k++) {
+ maskdata->DataBufferLo[k] = 0.0;
+ maskdata->DataBufferHi[k] = 0.0;
+ }
+ for (k = 0; k < ORDERLO+1; k++) {
+ maskdata->CorrBufLo[k] = 0.0;
+ maskdata->PreStateLoF[k] = 0.0;
+ maskdata->PreStateLoG[k] = 0.0;
+ maskdata->PostStateLoF[k] = 0.0;
+ maskdata->PostStateLoG[k] = 0.0;
+ }
+ for (k = 0; k < ORDERHI+1; k++) {
+ maskdata->CorrBufHi[k] = 0.0;
+ maskdata->PreStateHiF[k] = 0.0;
+ maskdata->PreStateHiG[k] = 0.0;
+ maskdata->PostStateHiF[k] = 0.0;
+ maskdata->PostStateHiG[k] = 0.0;
+ }
+
+ maskdata->OldEnergy = 10.0;
+
+ /* fill tables for transforms */
+ WebRtcIsac_InitTransform();
+
+ return;
+}
+
+void WebRtcIsac_InitPreFilterbank(PreFiltBankstr *prefiltdata)
+{
+ int k;
+
+ for (k = 0; k < QLOOKAHEAD; k++) {
+ prefiltdata->INLABUF1[k] = 0;
+ prefiltdata->INLABUF2[k] = 0;
+
+ prefiltdata->INLABUF1_float[k] = 0;
+ prefiltdata->INLABUF2_float[k] = 0;
+ }
+ for (k = 0; k < 2*(QORDER-1); k++) {
+ prefiltdata->INSTAT1[k] = 0;
+ prefiltdata->INSTAT2[k] = 0;
+ prefiltdata->INSTATLA1[k] = 0;
+ prefiltdata->INSTATLA2[k] = 0;
+
+ prefiltdata->INSTAT1_float[k] = 0;
+ prefiltdata->INSTAT2_float[k] = 0;
+ prefiltdata->INSTATLA1_float[k] = 0;
+ prefiltdata->INSTATLA2_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ prefiltdata->HPstates[0] = 0.0;
+ prefiltdata->HPstates[1] = 0.0;
+
+ prefiltdata->HPstates_float[0] = 0.0f;
+ prefiltdata->HPstates_float[1] = 0.0f;
+
+ return;
+}
+
+void WebRtcIsac_InitPostFilterbank(PostFiltBankstr *postfiltdata)
+{
+ int k;
+
+ for (k = 0; k < 2*POSTQORDER; k++) {
+ postfiltdata->STATE_0_LOWER[k] = 0;
+ postfiltdata->STATE_0_UPPER[k] = 0;
+
+ postfiltdata->STATE_0_LOWER_float[k] = 0;
+ postfiltdata->STATE_0_UPPER_float[k] = 0;
+ }
+
+ /* High pass filter states */
+ postfiltdata->HPstates1[0] = 0.0;
+ postfiltdata->HPstates1[1] = 0.0;
+
+ postfiltdata->HPstates2[0] = 0.0;
+ postfiltdata->HPstates2[1] = 0.0;
+
+ postfiltdata->HPstates1_float[0] = 0.0f;
+ postfiltdata->HPstates1_float[1] = 0.0f;
+
+ postfiltdata->HPstates2_float[0] = 0.0f;
+ postfiltdata->HPstates2_float[1] = 0.0f;
+
+ return;
+}
+
+
+void WebRtcIsac_InitPitchFilter(PitchFiltstr *pitchfiltdata)
+{
+ int k;
+
+ for (k = 0; k < PITCH_BUFFSIZE; k++) {
+ pitchfiltdata->ubuf[k] = 0.0;
+ }
+ pitchfiltdata->ystate[0] = 0.0;
+ for (k = 1; k < (PITCH_DAMPORDER); k++) {
+ pitchfiltdata->ystate[k] = 0.0;
+ }
+ pitchfiltdata->oldlagp[0] = 50.0;
+ pitchfiltdata->oldgainp[0] = 0.0;
+}
+
+void WebRtcIsac_InitWeightingFilter(WeightFiltstr *wfdata)
+{
+ int k;
+ double t, dtmp, dtmp2, denum, denum2;
+
+ for (k=0;kbuffer[k]=0.0;
+
+ for (k=0;kistate[k]=0.0;
+ wfdata->weostate[k]=0.0;
+ wfdata->whostate[k]=0.0;
+ }
+
+ /* next part should be in Matlab, writing to a global table */
+ t = 0.5;
+ denum = 1.0 / ((double) PITCH_WLPCWINLEN);
+ denum2 = denum * denum;
+ for (k=0;kwindow[k] = dtmp2 * dtmp2;
+ t++;
+ }
+}
+
+/* clear all buffers */
+void WebRtcIsac_InitPitchAnalysis(PitchAnalysisStruct *State)
+{
+ int k;
+
+ for (k = 0; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k++)
+ State->dec_buffer[k] = 0.0;
+ for (k = 0; k < 2*ALLPASSSECTIONS+1; k++)
+ State->decimator_state[k] = 0.0;
+ for (k = 0; k < 2; k++)
+ State->hp_state[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->whitened_buf[k] = 0.0;
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = 0.0;
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr_wght));
+
+ WebRtcIsac_InitPitchFilter(&(State->PFstr));
+
+ WebRtcIsac_InitWeightingFilter(&(State->Wghtstr));
+}
diff --git a/src/mod/codecs/mod_isac/isac.c b/src/mod/codecs/mod_isac/isac.c
new file mode 100644
index 0000000000..2199d571f9
--- /dev/null
+++ b/src/mod/codecs/mod_isac/isac.c
@@ -0,0 +1,2797 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * isac.c
+ *
+ * This C file contains the functions for the ISAC API
+ *
+ */
+
+#include "isac.h"
+#include "bandwidth_estimator.h"
+#include "crc.h"
+#include "entropy_coding.h"
+#include "codec.h"
+#include "structs.h"
+#include "signal_processing_library.h"
+#include "lpc_shape_swb16_tables.h"
+#include "os_specific_inline.h"
+
+#include
+#include
+#include
+#include
+
+#define BIT_MASK_DEC_INIT 0x0001
+#define BIT_MASK_ENC_INIT 0x0002
+
+#define LEN_CHECK_SUM_WORD8 4
+#define MAX_NUM_LAYERS 10
+
+
+/****************************************************************************
+ * UpdatePayloadSizeLimit()
+ *
+ * Call this function to update the limit on the payload size. The limit on
+ * payload size might change i) if a user ''directly changes the limit by
+ * calling xxx_setMaxPayloadSize() or xxx_setMaxRate(), or ii) indirectly
+ * when bandwidth is changing. The latter might be the result of bandwidth
+ * adaptation, or direct change of the bottleneck in instantaneous mode.
+ *
+ * This function takes the current overall limit on payload, and translate it
+ * to the limits on lower and upper-band. If the codec is in wideband mode
+ * then the overall limit and the limit on the lower-band is the same.
+ * Otherwise, a fraction of the limit should be allocated to lower-band
+ * leaving some room for the upper-band bit-stream. That is why an update
+ * of limit is required every time that the bandwidth is changing.
+ *
+ */
+static void UpdatePayloadSizeLimit(
+ ISACMainStruct *instISAC)
+{
+ WebRtc_Word16 lim30MsPayloadBytes;
+ WebRtc_Word16 lim60MsPayloadBytes;
+
+ lim30MsPayloadBytes = WEBRTC_SPL_MIN(
+ (instISAC->maxPayloadSizeBytes),
+ (instISAC->maxRateBytesPer30Ms));
+
+ lim60MsPayloadBytes = WEBRTC_SPL_MIN(
+ (instISAC->maxPayloadSizeBytes),
+ (instISAC->maxRateBytesPer30Ms << 1));
+
+ // The only time that iSAC will have 60 ms
+ // frame-size is when operating in wideband so
+ // there is no upper-band bit-stream
+
+ if(instISAC->bandwidthKHz == isac8kHz)
+ {
+ // at 8 kHz there is no upper-band bit-stream
+ // therefore the lower-band limit is as the overall
+ // limit.
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes60 =
+ lim60MsPayloadBytes;
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ lim30MsPayloadBytes;
+ }
+ else
+ {
+ // when in super-wideband, we only have 30 ms frames
+ // Do a rate allocation for the given limit.
+ if(lim30MsPayloadBytes > 250)
+ {
+ // 4/5 to lower-band the rest for upper-band
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ (lim30MsPayloadBytes << 2) / 5;
+ }
+ else if(lim30MsPayloadBytes > 200)
+ {
+ // for the interval of 200 to 250 the share of
+ // upper-band linearly grows from 20 to 50;
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ (lim30MsPayloadBytes << 1) / 5 + 100;
+ }
+ else
+ {
+ // allocate only 20 for upper-band
+ instISAC->instLB.ISACencLB_obj.payloadLimitBytes30 =
+ lim30MsPayloadBytes - 20;
+ }
+ instISAC->instUB.ISACencUB_obj.maxPayloadSizeBytes =
+ lim30MsPayloadBytes;
+ }
+}
+
+
+/****************************************************************************
+ * UpdateBottleneck()
+ *
+ * This function updates the bottleneck only if the codec is operating in
+ * channel-adaptive mode. Furthermore, as the update of bottleneck might
+ * result in an update of bandwidth, therefore, the bottlenech should be
+ * updated just right before the first 10ms of a frame is pushed into encoder.
+ *
+ */
+static void UpdateBottleneck(
+ ISACMainStruct *instISAC)
+{
+ // read the bottleneck from bandwidth estimator for the
+ // first 10 ms audio. This way, if there is a change
+ // in bandwidth upper and lower-band will be in sync.
+ if((instISAC->codingMode == 0) &&
+ (instISAC->instLB.ISACencLB_obj.buffer_index == 0) &&
+ (instISAC->instLB.ISACencLB_obj.frame_nb == 0))
+ {
+ WebRtc_Word32 bottleneck;
+ WebRtcIsac_GetUplinkBandwidth(&(instISAC->bwestimator_obj),
+ &bottleneck);
+
+ // Adding hysteresis when increasing signal bandwidth
+ if((instISAC->bandwidthKHz == isac8kHz)
+ && (bottleneck > 37000)
+ && (bottleneck < 41000))
+ {
+ bottleneck = 37000;
+ }
+
+ // switching from 12 kHz to 16 kHz is not allowed at this revision
+ // If we let this happen, we have to take care of buffer_index and
+ // the last LPC vector.
+ if((instISAC->bandwidthKHz != isac16kHz) &&
+ (bottleneck > 46000))
+ {
+ bottleneck = 46000;
+ }
+
+ // we might need a rate allocation.
+ if(instISAC->encoderSamplingRateKHz == kIsacWideband)
+ {
+ // wideband is the only choise we have here.
+ instISAC->instLB.ISACencLB_obj.bottleneck =
+ (bottleneck > 32000)? 32000:bottleneck;
+ instISAC->bandwidthKHz = isac8kHz;
+ }
+ else
+ {
+ // do the rate-allosation and get the new bandwidth.
+ enum ISACBandwidth bandwidth;
+ WebRtcIsac_RateAllocation(bottleneck,
+ &(instISAC->instLB.ISACencLB_obj.bottleneck),
+ &(instISAC->instUB.ISACencUB_obj.bottleneck),
+ &bandwidth);
+ if(bandwidth != isac8kHz)
+ {
+ instISAC->instLB.ISACencLB_obj.new_framelength = 480;
+ }
+ if(bandwidth != instISAC->bandwidthKHz)
+ {
+ // bandwidth is changing.
+ instISAC->bandwidthKHz = bandwidth;
+ UpdatePayloadSizeLimit(instISAC);
+ if(bandwidth == isac12kHz)
+ {
+ instISAC->instLB.ISACencLB_obj.buffer_index = 0;
+ }
+ // currently we don't let the bandwidth to switch to 16 kHz
+ // if in adaptive mode. If we let this happen, we have to take
+ // car of buffer_index and the last LPC vector.
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ * GetSendBandwidthInfo()
+ *
+ * This is called to get the bandwidth info. This info is the bandwidth and
+ * and the jitter of 'there-to-here' channel, estimated 'here.' These info
+ * is signaled in an in-band fashion to the otherside.
+ *
+ * The call to the bandwidth estimator trigers a recursive averaging which
+ * has to be synchronized between encoder & decoder, therefore. The call to
+ * BWE should be once per packet. As the BWE info is inserted into bit-stream
+ * we need a valid info right before the encodeLB function is going to
+ * generating a bit-stream. That is when lower-band buffer has already 20ms
+ * of audio, and the 3rd block of 10ms is going to be injected into encoder.
+ *
+ * Inputs:
+ * - instISAC : iSAC instance.
+ *
+ * Outputs:
+ * - bandwidthIndex : an index which has to be encoded in
+ * lower-band bit-stream, indicating the
+ * bandwidth of there-to-here channel.
+ * - jitterInfo : this indicates if the jitter is high
+ * or low and it is encoded in upper-band
+ * bit-stream.
+ *
+ */
+static void GetSendBandwidthInfo(
+ ISACMainStruct* instISAC,
+ WebRtc_Word16* bandwidthIndex,
+ WebRtc_Word16* jitterInfo)
+{
+ if((instISAC->instLB.ISACencLB_obj.buffer_index ==
+ (FRAMESAMPLES_10ms << 1)) &&
+ (instISAC->instLB.ISACencLB_obj.frame_nb == 0))
+ {
+ /* bandwidth estimation and coding */
+ WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj),
+ bandwidthIndex, jitterInfo, instISAC->decoderSamplingRateKHz);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_AssignSize(...)
+ *
+ * This function returns the size of the ISAC instance, so that the instance
+ * can be created out side iSAC.
+ *
+ * Output:
+ * - sizeinbytes : number of bytes needed to allocate for the
+ * instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_AssignSize(
+ int *sizeInBytes)
+{
+ *sizeInBytes = sizeof(ISACMainStruct) * 2 / sizeof(WebRtc_Word16);
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Assign(...)
+ *
+ * This function assignes the memory already created to the ISAC instance.
+ *
+ * Input:
+ * - ISAC_main_inst : address of the pointer to the coder instance.
+ * - instISAC_Addr : the already allocaded memeory, where we put the
+ * iSAC struct
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_Assign(
+ ISACStruct** ISAC_main_inst,
+ void* instISAC_Addr)
+{
+ if(instISAC_Addr != NULL)
+ {
+ ISACMainStruct* instISAC = (ISACMainStruct*)instISAC_Addr;
+ instISAC->errorCode = 0;
+ instISAC->initFlag = 0;
+
+ // Assign the address
+ *ISAC_main_inst = (ISACStruct*)instISAC_Addr;
+
+ // Default is wideband.
+ instISAC->encoderSamplingRateKHz = kIsacWideband;
+ instISAC->decoderSamplingRateKHz = kIsacWideband;
+ instISAC->bandwidthKHz = isac8kHz;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - ISAC_main_inst : address of the pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_Create(
+ ISACStruct** ISAC_main_inst)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)WEBRTC_SPL_VNEW(ISACMainStruct, 1);
+ *ISAC_main_inst = (ISACStruct*)instISAC;
+ if(*ISAC_main_inst != NULL)
+ {
+ instISAC->errorCode = 0;
+ instISAC->initFlag = 0;
+ // Default is wideband
+ instISAC->bandwidthKHz = isac8kHz;
+ instISAC->encoderSamplingRateKHz = kIsacWideband;
+ instISAC->decoderSamplingRateKHz = kIsacWideband;
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : a ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_Free(
+ ISACStruct* ISAC_main_inst)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+ WEBRTC_SPL_FREE(instISAC);
+ return 0;
+}
+
+
+/****************************************************************************
+ * EncoderInitLb(...) - internal function for initialization of
+ * Lower Band
+ * EncoderInitUb(...) - internal function for initialization of
+ * Upper Band
+ * WebRtcIsac_EncoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 -> Bit rate and frame length are automatically
+ * adjusted to available bandwidth on
+ * transmission channel, applicable just to
+ * wideband mode.
+ * 1 -> User sets a frame length and a target bit
+ * rate which is taken as the maximum
+ * short-term average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+static WebRtc_Word16 EncoderInitLb(
+ ISACLBStruct* instLB,
+ WebRtc_Word16 codingMode,
+ enum IsacSamplingRate sampRate)
+{
+ WebRtc_Word16 statusInit = 0;
+ int k;
+
+ /* Init stream vector to zero */
+ for(k=0; k < STREAM_SIZE_MAX_60; k++)
+ {
+ instLB->ISACencLB_obj.bitstr_obj.stream[k] = 0;
+ }
+
+ if((codingMode == 1) || (sampRate == kIsacSuperWideband))
+ {
+ // 30 ms frame-size if either in super-wideband or
+ // instanteneous mode (I-mode)
+ instLB->ISACencLB_obj.new_framelength = 480;
+ }
+ else
+ {
+ instLB->ISACencLB_obj.new_framelength = INITIAL_FRAMESAMPLES;
+ }
+
+ WebRtcIsac_InitMasking(&instLB->ISACencLB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPreFilterbank(&instLB->ISACencLB_obj.prefiltbankstr_obj);
+ WebRtcIsac_InitPitchFilter(&instLB->ISACencLB_obj.pitchfiltstr_obj);
+ WebRtcIsac_InitPitchAnalysis(
+ &instLB->ISACencLB_obj.pitchanalysisstr_obj);
+
+
+ instLB->ISACencLB_obj.buffer_index = 0;
+ instLB->ISACencLB_obj.frame_nb = 0;
+ /* default for I-mode */
+ instLB->ISACencLB_obj.bottleneck = 32000;
+ instLB->ISACencLB_obj.current_framesamples = 0;
+ instLB->ISACencLB_obj.s2nr = 0;
+ instLB->ISACencLB_obj.payloadLimitBytes30 = STREAM_SIZE_MAX_30;
+ instLB->ISACencLB_obj.payloadLimitBytes60 = STREAM_SIZE_MAX_60;
+ instLB->ISACencLB_obj.maxPayloadBytes = STREAM_SIZE_MAX_60;
+ instLB->ISACencLB_obj.maxRateInBytes = STREAM_SIZE_MAX_30;
+ instLB->ISACencLB_obj.enforceFrameSize = 0;
+ /* invalid value prevents getRedPayload to
+ run before encoder is called */
+ instLB->ISACencLB_obj.lastBWIdx = -1;
+ return statusInit;
+}
+
+static WebRtc_Word16 EncoderInitUb(
+ ISACUBStruct* instUB,
+ WebRtc_Word16 bandwidth)
+{
+ WebRtc_Word16 statusInit = 0;
+ int k;
+
+ /* Init stream vector to zero */
+ for(k = 0; k < STREAM_SIZE_MAX_60; k++)
+ {
+ instUB->ISACencUB_obj.bitstr_obj.stream[k] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instUB->ISACencUB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPreFilterbank(&instUB->ISACencUB_obj.prefiltbankstr_obj);
+
+ if(bandwidth == isac16kHz)
+ {
+ instUB->ISACencUB_obj.buffer_index = LB_TOTAL_DELAY_SAMPLES;
+ }
+ else
+ {
+ instUB->ISACencUB_obj.buffer_index = 0;
+ }
+ /* default for I-mode */
+ instUB->ISACencUB_obj.bottleneck = 32000;
+ // These store the limits for the wideband + super-wideband bit-stream.
+ instUB->ISACencUB_obj.maxPayloadSizeBytes = STREAM_SIZE_MAX_30 << 1;
+ // This has to be updated after each lower-band encoding to guarantee
+ // a correct payload-limitation.
+ instUB->ISACencUB_obj.numBytesUsed = 0;
+ memset(instUB->ISACencUB_obj.data_buffer_float, 0,
+ (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES) * sizeof(float));
+
+ memcpy(&(instUB->ISACencUB_obj.lastLPCVec),
+ WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+
+ return statusInit;
+}
+
+
+WebRtc_Word16 WebRtcIsac_EncoderInit(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 codingMode)
+{
+ ISACMainStruct *instISAC;
+ WebRtc_Word16 status;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if((codingMode != 0) && (codingMode != 1))
+ {
+ instISAC->errorCode = ISAC_DISALLOWED_CODING_MODE;
+ return -1;
+ }
+ // default bottleneck
+ instISAC->bottleneck = MAX_ISAC_BW;
+
+ if(instISAC->encoderSamplingRateKHz == kIsacWideband)
+ {
+ instISAC->bandwidthKHz = isac8kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+ }
+ else
+ {
+ instISAC->bandwidthKHz = isac16kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+ }
+
+ // Channel-adaptive = 0; Instantaneous (Channel-independent) = 1;
+ instISAC->codingMode = codingMode;
+
+ WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+ instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+
+ WebRtcIsac_InitRateModel(&instISAC->rate_data_obj);
+ /* default for I-mode */
+ instISAC->MaxDelay = 10.0;
+
+ status = EncoderInitLb(&instISAC->instLB, codingMode,
+ instISAC->encoderSamplingRateKHz);
+ if(status < 0)
+ {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+
+ if(instISAC->encoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ // Initialize encoder filter-bank.
+ memset(instISAC->analysisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+ memset(instISAC->analysisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+
+ status = EncoderInitUb(&(instISAC->instUB),
+ instISAC->bandwidthKHz);
+ if(status < 0)
+ {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ }
+ // Initializtion is successful, set the flag
+ instISAC->initFlag |= BIT_MASK_ENC_INIT;
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms frame(s) and inserts it into a package.
+ * Input speech length has to be 160 samples (10ms). The encoder buffers those
+ * 10ms frames until it reaches the chosen Framesize (480 or 960 samples
+ * corresponding to 30 or 60 ms frames), and then proceeds to the encoding.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : 0 - The buffer didn't reach the chosen
+ * frameSize so it keeps buffering speech
+ * samples.
+ * : -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_Encode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* speechIn,
+ WebRtc_Word16* encoded)
+{
+ ISACMainStruct* instISAC;
+ ISACLBStruct* instLB;
+ ISACUBStruct* instUB;
+
+ float inFrame[FRAMESAMPLES_10ms];
+ WebRtc_Word16 speechInLB[FRAMESAMPLES_10ms];
+ WebRtc_Word16 speechInUB[FRAMESAMPLES_10ms];
+ WebRtc_Word16 streamLenLB;
+ WebRtc_Word16 streamLenUB;
+ WebRtc_Word16 streamLen;
+ WebRtc_Word16 k;
+ WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded;
+ int garbageLen;
+ WebRtc_Word32 bottleneck;
+ WebRtc_Word16 bottleneckIdx = 0;
+ WebRtc_Word16 jitterInfo = 0;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+ instLB = &(instISAC->instLB);
+ instUB = &(instISAC->instUB);
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if(instISAC->encoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ WebRtcSpl_AnalysisQMF(speechIn, speechInLB, speechInUB,
+ instISAC->analysisFBState1, instISAC->analysisFBState2);
+
+ /* convert from fixed to floating point */
+ for(k = 0; k < FRAMESAMPLES_10ms; k++)
+ {
+ inFrame[k] = (float)speechInLB[k];
+ }
+ }
+ else
+ {
+ for(k = 0; k < FRAMESAMPLES_10ms; k++)
+ {
+ inFrame[k] = (float) speechIn[k];
+ }
+ }
+
+ /* add some noise to avoid denormal numbers */
+ inFrame[0] += (float)1.23455334e-3;
+ inFrame[1] -= (float)2.04324239e-3;
+ inFrame[2] += (float)1.90854954e-3;
+ inFrame[9] += (float)1.84854878e-3;
+
+
+ // This function will update the bottleneck if required
+ UpdateBottleneck(instISAC);
+
+ // Get the bandwith information which has to be sent to the other side
+ GetSendBandwidthInfo(instISAC, &bottleneckIdx, &jitterInfo);
+
+ //
+ // ENCODE LOWER-BAND
+ //
+ streamLenLB = WebRtcIsac_EncodeLb(inFrame, &instLB->ISACencLB_obj,
+ instISAC->codingMode, bottleneckIdx);
+
+ if(streamLenLB < 0)
+ {
+ return -1;
+ }
+
+ if(instISAC->encoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ instUB = &(instISAC->instUB);
+
+ // convert to float
+ for(k = 0; k < FRAMESAMPLES_10ms; k++)
+ {
+ inFrame[k] = (float) speechInUB[k];
+ }
+
+ /* add some noise to avoid denormal numbers */
+ inFrame[0] += (float)1.23455334e-3;
+ inFrame[1] -= (float)2.04324239e-3;
+ inFrame[2] += (float)1.90854954e-3;
+ inFrame[9] += (float)1.84854878e-3;
+
+ // Tell to upper-band the number of bytes used so far.
+ // This is for payload limitation.
+ instUB->ISACencUB_obj.numBytesUsed = streamLenLB + 1 +
+ LEN_CHECK_SUM_WORD8;
+
+ //
+ // ENCODE UPPER-BAND
+ //
+ switch(instISAC->bandwidthKHz)
+ {
+ case isac12kHz:
+ {
+ streamLenUB = WebRtcIsac_EncodeUb12(inFrame,
+ &instUB->ISACencUB_obj,
+ jitterInfo);
+ break;
+ }
+ case isac16kHz:
+ {
+ streamLenUB = WebRtcIsac_EncodeUb16(inFrame,
+ &instUB->ISACencUB_obj,
+ jitterInfo);
+ break;
+ }
+ case isac8kHz:
+ {
+ streamLenUB = 0;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if((streamLenUB < 0) &&
+ (streamLenUB != -ISAC_PAYLOAD_LARGER_THAN_LIMIT))
+ {
+ // an error has happened but this is not the error due to a
+ // bit-stream larger than the limit
+ return -1;
+ }
+
+ if(streamLenLB == 0)
+ {
+ return 0;
+ }
+
+ // One bite is allocated for the length. According to older decoders
+ // so the length bit-stream plus one byte for size and
+ // LEN_CHECK_SUM_WORD8 for the checksum should be less than or equal
+ // to 255.
+ if((streamLenUB > (255 - (LEN_CHECK_SUM_WORD8 + 1))) ||
+ (streamLenUB == -ISAC_PAYLOAD_LARGER_THAN_LIMIT))
+ {
+ // we have got a too long bit-stream we skip the upper-band
+ // bit-stream for this frame.
+ streamLenUB = 0;
+ }
+
+ memcpy(ptrEncodedUW8, instLB->ISACencLB_obj.bitstr_obj.stream,
+ streamLenLB);
+ streamLen = streamLenLB;
+ if(streamLenUB > 0)
+ {
+ ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)(streamLenUB + 1 +
+ LEN_CHECK_SUM_WORD8);
+ memcpy(&ptrEncodedUW8[streamLenLB + 1],
+ instUB->ISACencUB_obj.bitstr_obj.stream, streamLenUB);
+ streamLen += ptrEncodedUW8[streamLenLB];
+ }
+ else
+ {
+ ptrEncodedUW8[streamLenLB] = 0;
+ }
+ }
+ else
+ {
+ if(streamLenLB == 0)
+ {
+ return 0;
+ }
+ memcpy(ptrEncodedUW8, instLB->ISACencLB_obj.bitstr_obj.stream,
+ streamLenLB);
+ streamLenUB = 0;
+ streamLen = streamLenLB;
+ }
+
+ // Add Garbage if required.
+ WebRtcIsac_GetUplinkBandwidth(&instISAC->bwestimator_obj, &bottleneck);
+ if(instISAC->codingMode == 0)
+ {
+ int minBytes;
+ int limit;
+ WebRtc_UWord8* ptrGarbage;
+
+ instISAC->MaxDelay = (double)WebRtcIsac_GetUplinkMaxDelay(
+ &instISAC->bwestimator_obj);
+
+ /* update rate model and get minimum number of bytes in this packet */
+ minBytes = WebRtcIsac_GetMinBytes(&(instISAC->rate_data_obj),
+ streamLen, instISAC->instLB.ISACencLB_obj.current_framesamples,
+ bottleneck, instISAC->MaxDelay, instISAC->bandwidthKHz);
+
+ /* Make sure MinBytes does not exceed packet size limit */
+ if(instISAC->bandwidthKHz == isac8kHz)
+ {
+ if(instLB->ISACencLB_obj.current_framesamples == FRAMESAMPLES)
+ {
+ limit = instLB->ISACencLB_obj.payloadLimitBytes30;
+ }
+ else
+ {
+ limit = instLB->ISACencLB_obj.payloadLimitBytes60;
+ }
+ }
+ else
+ {
+ limit = instUB->ISACencUB_obj.maxPayloadSizeBytes;
+ }
+ minBytes = (minBytes > limit)? limit:minBytes;
+
+ /* Make sure we don't allow more than 255 bytes of garbage data.
+ We store the length of the garbage data in 8 bits in the bitstream,
+ 255 is the max garbage length we can signal using 8 bits. */
+ if((instISAC->bandwidthKHz == isac8kHz) ||
+ (streamLenUB == 0))
+ {
+ ptrGarbage = &ptrEncodedUW8[streamLenLB];
+ limit = streamLen + 255;
+ }
+ else
+ {
+ ptrGarbage = &ptrEncodedUW8[streamLenLB + 1 + streamLenUB];
+ limit = streamLen + (255 - ptrEncodedUW8[streamLenLB]);
+ }
+ minBytes = (minBytes > limit)? limit:minBytes;
+
+ garbageLen = (minBytes > streamLen)? (minBytes - streamLen):0;
+
+ /* Save data for creation of multiple bitstreams */
+ //ISACencLB_obj->SaveEnc_obj.minBytes = MinBytes;
+
+ /* if bitstream is too short, add garbage at the end */
+ if(garbageLen > 0)
+ {
+ for(k = 0; k < garbageLen; k++)
+ {
+ ptrGarbage[k] = (WebRtc_UWord8)(rand() & 0xFF);
+ }
+
+ // for a correct length of the upper-band bit-stream together
+ // with the garbage. Garbage is embeded in upper-band bit-stream.
+ // That is the only way to preserve backward compatibility.
+ if((instISAC->bandwidthKHz == isac8kHz) ||
+ (streamLenUB == 0))
+ {
+ ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)garbageLen;
+ }
+ else
+ {
+ ptrEncodedUW8[streamLenLB] += (WebRtc_UWord8)garbageLen;
+ // write the length of the garbage at the end of the upper-band
+ // bit-stream, if exists. This helps for sanity check.
+ ptrEncodedUW8[streamLenLB + 1 + streamLenUB] = (WebRtc_UWord8)garbageLen;
+
+ }
+
+ streamLen += garbageLen;
+ }
+ }
+ else
+ {
+ /* update rate model */
+ WebRtcIsac_UpdateRateModel(&instISAC->rate_data_obj, streamLen,
+ instISAC->instLB.ISACencLB_obj.current_framesamples, bottleneck);
+ garbageLen = 0;
+ }
+
+ // Generate CRC if required.
+ if((instISAC->bandwidthKHz != isac8kHz) &&
+ (streamLenUB > 0))
+ {
+ WebRtc_UWord32 crc;
+
+ WebRtcIsac_GetCrc((WebRtc_Word16*)(&(ptrEncodedUW8[streamLenLB + 1])),
+ streamLenUB + garbageLen, &crc);
+#ifndef WEBRTC_BIG_ENDIAN
+ for(k = 0; k < LEN_CHECK_SUM_WORD8; k++)
+ {
+ ptrEncodedUW8[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF);
+ }
+#else
+ memcpy(&ptrEncodedUW8[streamLenLB + streamLenUB + 1], &crc,
+ LEN_CHECK_SUM_WORD8);
+#endif
+ }
+
+ return streamLen;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the recieved bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 3! Rates larger than the bottleneck of the codec will be limited
+ * to the current bottleneck.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : Index of bandwidth estimate to put in new
+ * bitstream
+ * - rate : target rate of the transcoder is bits/sec.
+ * Valid values are the accepted rate in iSAC,
+ * i.e. 10000 to 56000.
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error or called in SWB mode
+ * NOTE! No error code is written to
+ * the struct since it is only allowed to read
+ * the struct.
+ */
+WebRtc_Word16 WebRtcIsac_GetNewBitStream(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 bweIndex,
+ WebRtc_Word16 jitterInfo,
+ WebRtc_Word32 rate,
+ WebRtc_Word16* encoded,
+ WebRtc_Word16 isRCU)
+{
+ Bitstr iSACBitStreamInst; /* Local struct for bitstream handling */
+ WebRtc_Word16 streamLenLB;
+ WebRtc_Word16 streamLenUB;
+ WebRtc_Word16 totalStreamLen;
+ double gain2;
+ double gain1;
+ float scale;
+ enum ISACBandwidth bandwidthKHz;
+ double rateLB;
+ double rateUB;
+ WebRtc_Word32 currentBN;
+ ISACMainStruct* instISAC;
+ WebRtc_UWord8* encodedPtrUW8 = (WebRtc_UWord8*)encoded;
+ WebRtc_UWord32 crc;
+#ifndef WEBRTC_BIG_ENDIAN
+ WebRtc_Word16 k;
+#endif
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ return -1;
+ }
+
+ // Get the bottleneck of this iSAC and limit the
+ // given rate to the current bottleneck.
+ WebRtcIsac_GetUplinkBw(ISAC_main_inst, ¤tBN);
+ if(rate > currentBN)
+ {
+ rate = currentBN;
+ }
+
+ if(WebRtcIsac_RateAllocation(rate, &rateLB, &rateUB, &bandwidthKHz) < 0)
+ {
+ return -1;
+ }
+
+ // Cannot transcode from 16 kHz to 12 kHz
+ if((bandwidthKHz == isac12kHz) &&
+ (instISAC->bandwidthKHz == isac16kHz))
+ {
+ return -1;
+ }
+
+ // These gains are in dB
+ // gain for the given rate.
+ gain1 = WebRtcIsac_GetSnr(rateLB,
+ instISAC->instLB.ISACencLB_obj.current_framesamples);
+ // gain of this iSAC
+ gain2 = WebRtcIsac_GetSnr(
+ instISAC->instLB.ISACencLB_obj.bottleneck,
+ instISAC->instLB.ISACencLB_obj.current_framesamples);
+
+ // scale is the ratio of two gains in normal domain.
+ scale = (float)pow(10, (gain1 - gain2) / 20.0);
+ // change the scale if this is a RCU bit-stream.
+ scale = (isRCU)? (scale * RCU_TRANSCODING_SCALE):scale;
+
+ streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+ &instISAC->instLB.ISACencLB_obj.SaveEnc_obj, &iSACBitStreamInst,
+ bweIndex, scale);
+
+ if(streamLenLB < 0)
+ {
+ return -1;
+ }
+
+ /* convert from bytes to WebRtc_Word16 */
+ memcpy(encoded, iSACBitStreamInst.stream, streamLenLB);
+
+ if(bandwidthKHz == isac8kHz)
+ {
+ return streamLenLB;
+ }
+
+ totalStreamLen = streamLenLB;
+ // super-wideband is always at 30ms.
+ // These gains are in dB
+ // gain for the given rate.
+ gain1 = WebRtcIsac_GetSnr(rateUB, FRAMESAMPLES);
+ // gain of this iSAC
+ gain2 = WebRtcIsac_GetSnr(
+ instISAC->instUB.ISACencUB_obj.bottleneck, FRAMESAMPLES);
+
+ // scale is the ratio of two gains in normal domain.
+ scale = (float)pow(10, (gain1 - gain2) / 20.0);
+
+ // change the scale if this is a RCU bit-stream.
+ scale = (isRCU)? (scale * RCU_TRANSCODING_SCALE_UB):scale;
+
+ switch(instISAC->bandwidthKHz)
+ {
+ case isac12kHz:
+ {
+ streamLenUB = WebRtcIsac_EncodeStoredDataUb12(
+ &(instISAC->instUB.ISACencUB_obj.SaveEnc_obj),
+ &iSACBitStreamInst, jitterInfo, scale);
+ break;
+ }
+ case isac16kHz:
+ {
+ streamLenUB = WebRtcIsac_EncodeStoredDataUb16(
+ &(instISAC->instUB.ISACencUB_obj.SaveEnc_obj),
+ &iSACBitStreamInst, jitterInfo, scale);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ if(streamLenUB < 0)
+ {
+ return -1;
+ }
+
+ if(streamLenUB + 1 + LEN_CHECK_SUM_WORD8 > 255)
+ {
+ return streamLenLB;
+ }
+
+ totalStreamLen = streamLenLB + streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+ encodedPtrUW8[streamLenLB] = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+
+ memcpy(&encodedPtrUW8[streamLenLB+1], iSACBitStreamInst.stream,
+ streamLenUB);
+
+ WebRtcIsac_GetCrc((WebRtc_Word16*)(&(encodedPtrUW8[streamLenLB + 1])),
+ streamLenUB, &crc);
+#ifndef WEBRTC_BIG_ENDIAN
+ for(k = 0; k < LEN_CHECK_SUM_WORD8; k++)
+ {
+ encodedPtrUW8[totalStreamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF);
+ }
+#else
+ memcpy(&encodedPtrUW8[streamLenLB + streamLenUB + 1], &crc,
+ LEN_CHECK_SUM_WORD8);
+#endif
+
+
+ return totalStreamLen;
+}
+
+
+/****************************************************************************
+ * DecoderInitLb(...) - internal function for initialization of
+ * Lower Band
+ * DecoderInitUb(...) - internal function for initialization of
+ * Upper Band
+ * WebRtcIsac_DecoderInit(...) - API function
+ *
+ * This function initializes a ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ *
+ * Return value
+ * : 0 - Ok
+ * -1 - Error
+ */
+static WebRtc_Word16 DecoderInitLb(
+ ISACLBStruct* instISAC)
+{
+ int i;
+ /* Init stream vector to zero */
+ for (i=0; iISACdecLB_obj.bitstr_obj.stream[i] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instISAC->ISACdecLB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPostFilterbank(
+ &instISAC->ISACdecLB_obj.postfiltbankstr_obj);
+ WebRtcIsac_InitPitchFilter(&instISAC->ISACdecLB_obj.pitchfiltstr_obj);
+
+ return (0);
+}
+
+static WebRtc_Word16 DecoderInitUb(
+ ISACUBStruct* instISAC)
+{
+ int i;
+ /* Init stream vector to zero */
+ for (i = 0; i < STREAM_SIZE_MAX_60; i++)
+ {
+ instISAC->ISACdecUB_obj.bitstr_obj.stream[i] = 0;
+ }
+
+ WebRtcIsac_InitMasking(&instISAC->ISACdecUB_obj.maskfiltstr_obj);
+ WebRtcIsac_InitPostFilterbank(
+ &instISAC->ISACdecUB_obj.postfiltbankstr_obj);
+ return (0);
+}
+
+WebRtc_Word16 WebRtcIsac_DecoderInit(
+ ISACStruct *ISAC_main_inst)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if(DecoderInitLb(&instISAC->instLB) < 0)
+ {
+ return -1;
+ }
+
+ if(instISAC->decoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ memset(instISAC->synthesisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+ memset(instISAC->synthesisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+
+ if(DecoderInitUb(&(instISAC->instUB)) < 0)
+ {
+ return -1;
+ }
+ }
+
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ WebRtcIsac_InitBandwidthEstimator(&instISAC->bwestimator_obj,
+ instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+ }
+
+ instISAC->initFlag |= BIT_MASK_DEC_INIT;
+
+ instISAC->resetFlag_8kHz = 0;
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_UpdateBwEstimate(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts)
+{
+ ISACMainStruct *instISAC;
+ Bitstr streamdata;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* check if decoder initiated */
+ if((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+ BIT_MASK_DEC_INIT)
+ {
+ instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if(packet_size <= 0)
+ {
+ /* return error code if the packet length is null */
+ instISAC->errorCode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for(k = 0; k < 10; k++)
+ {
+ streamdata.stream[k] = (WebRtc_UWord8) ((encoded[k>>1] >>
+ ((k&1) << 3)) & 0xFF);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ err = WebRtcIsac_EstimateBandwidth(&instISAC->bwestimator_obj, &streamdata,
+ packet_size, rtp_seq_number, send_ts, arr_ts,
+ instISAC->encoderSamplingRateKHz,
+ instISAC->decoderSamplingRateKHz);
+
+ if(err < 0)
+ {
+ /* return error code if something went wrong */
+ instISAC->errorCode = -err;
+ return -1;
+ }
+
+ return 0;
+}
+
+static WebRtc_Word16 Decode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word16 lenEncodedBytes,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType,
+ WebRtc_Word16 isRCUPayload)
+{
+ /* number of samples (480 or 960), output from decoder
+ that were actually used in the encoder/decoder
+ (determined on the fly) */
+ ISACMainStruct* instISAC;
+ ISACUBDecStruct* decInstUB;
+ ISACLBDecStruct* decInstLB;
+
+ WebRtc_Word16 numSamplesLB;
+ WebRtc_Word16 numSamplesUB;
+ WebRtc_Word16 speechIdx;
+ float outFrame[MAX_FRAMESAMPLES];
+ WebRtc_Word16 outFrameLB[MAX_FRAMESAMPLES];
+ WebRtc_Word16 outFrameUB[MAX_FRAMESAMPLES];
+ WebRtc_Word16 numDecodedBytesLB;
+ WebRtc_Word16 numDecodedBytesUB;
+ WebRtc_Word16 lenEncodedLBBytes;
+ WebRtc_Word16 validChecksum = 1;
+ WebRtc_Word16 k;
+ WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded;
+ WebRtc_UWord16 numLayer;
+ WebRtc_Word16 totSizeBytes;
+ WebRtc_Word16 err;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+ decInstUB = &(instISAC->instUB.ISACdecUB_obj);
+ decInstLB = &(instISAC->instLB.ISACdecLB_obj);
+
+ /* check if decoder initiated */
+ if((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+ BIT_MASK_DEC_INIT)
+ {
+ instISAC->errorCode = ISAC_DECODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if(lenEncodedBytes <= 0)
+ {
+ /* return error code if the packet length is null */
+ instISAC->errorCode = ISAC_EMPTY_PACKET;
+ return -1;
+ }
+
+ // the size of the rncoded lower-band is bounded by
+ // STREAM_SIZE_MAX,
+ // If a payload with the size larger than STREAM_SIZE_MAX
+ // is received, it is not considered erroneous.
+ lenEncodedLBBytes = (lenEncodedBytes > STREAM_SIZE_MAX)
+ ? STREAM_SIZE_MAX:lenEncodedBytes;
+
+ // Copy to lower-band bit-stream structure
+ memcpy(instISAC->instLB.ISACdecLB_obj.bitstr_obj.stream, ptrEncodedUW8,
+ lenEncodedLBBytes);
+
+ // Regardless of that the current codec is setup to work in
+ // wideband or super-wideband, the decoding of the lower-band
+ // has to be performed.
+ numDecodedBytesLB = WebRtcIsac_DecodeLb(outFrame, decInstLB,
+ &numSamplesLB, isRCUPayload);
+
+ // Check for error
+ if((numDecodedBytesLB < 0) ||
+ (numDecodedBytesLB > lenEncodedLBBytes) ||
+ (numSamplesLB > MAX_FRAMESAMPLES))
+ {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ // Error Check, we accept multi-layer bit-stream
+ // This will limit number of iterations of the
+ // while loop. Even withouut this the number of iterations
+ // is limited.
+ numLayer = 1;
+ totSizeBytes = numDecodedBytesLB;
+ while(totSizeBytes != lenEncodedBytes)
+ {
+ if((totSizeBytes > lenEncodedBytes) ||
+ (ptrEncodedUW8[totSizeBytes] == 0) ||
+ (numLayer > MAX_NUM_LAYERS))
+ {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+ totSizeBytes += ptrEncodedUW8[totSizeBytes];
+ numLayer++;
+ }
+
+ if(instISAC->decoderSamplingRateKHz == kIsacWideband)
+ {
+ for(k = 0; k < numSamplesLB; k++)
+ {
+ if(outFrame[k] > 32767)
+ {
+ decoded[k] = 32767;
+ }
+ else if(outFrame[k] < -32768)
+ {
+ decoded[k] = -32768;
+ }
+ else
+ {
+ decoded[k] = (WebRtc_Word16)WebRtcIsac_lrint(outFrame[k]);
+ }
+ }
+ numSamplesUB = 0;
+ }
+ else
+ {
+ WebRtc_UWord32 crc;
+ // We don't accept larger than 30ms (480 samples at lower-band)
+ // frame-size.
+ for(k = 0; k < numSamplesLB; k++)
+ {
+ if(outFrame[k] > 32767)
+ {
+ outFrameLB[k] = 32767;
+ }
+ else if(outFrame[k] < -32768)
+ {
+ outFrameLB[k] = -32768;
+ }
+ else
+ {
+ outFrameLB[k] = (WebRtc_Word16)WebRtcIsac_lrint(outFrame[k]);
+ }
+ }
+
+ //numSamplesUB = numSamplesLB;
+
+ // Check for possible error, and if upper-band stream exist.
+ if(numDecodedBytesLB == lenEncodedBytes)
+ {
+ // Decoding was successful. No super-wideband bitstream
+ // exists.
+ numSamplesUB = numSamplesLB;
+ memset(outFrameUB, 0, sizeof(WebRtc_Word16) * numSamplesUB);
+
+ // Prepare for the potential increase of signal bandwidth
+ instISAC->resetFlag_8kHz = 2;
+ }
+ else
+ {
+ // this includes the check sum and the bytes that stores the
+ // length
+ WebRtc_Word16 lenNextStream = ptrEncodedUW8[numDecodedBytesLB];
+
+ // Is this garbage or valid super-wideband bit-stream?
+ // Check if checksum is valid
+ if(lenNextStream <= (LEN_CHECK_SUM_WORD8 + 1))
+ {
+ // such a small second layer cannot be super-wideband layer.
+ // It must be a short garbage.
+ validChecksum = 0;
+ }
+ else
+ {
+ // Run CRC to see if the checksum match.
+ WebRtcIsac_GetCrc((WebRtc_Word16*)(
+ &ptrEncodedUW8[numDecodedBytesLB + 1]),
+ lenNextStream - LEN_CHECK_SUM_WORD8 - 1, &crc);
+
+ validChecksum = 1;
+ for(k = 0; k < LEN_CHECK_SUM_WORD8; k++)
+ {
+ validChecksum &= (((crc >> (24 - k * 8)) & 0xFF) ==
+ ptrEncodedUW8[numDecodedBytesLB + lenNextStream -
+ LEN_CHECK_SUM_WORD8 + k]);
+ }
+ }
+
+ if(!validChecksum)
+ {
+ // this is a garbage, we have received a wideband
+ // bit-stream with garbage
+ numSamplesUB = numSamplesLB;
+ memset(outFrameUB, 0, sizeof(WebRtc_Word16) * numSamplesUB);
+ }
+ else
+ {
+ // A valid super-wideband biststream exists.
+ enum ISACBandwidth bandwidthKHz;
+ WebRtc_Word32 maxDelayBit;
+
+ //instISAC->bwestimator_obj.incomingStreamSampFreq =
+ // kIsacSuperWideband;
+ // If we have super-wideband bit-stream, we cannot
+ // have 60 ms frame-size.
+ if(numSamplesLB > FRAMESAMPLES)
+ {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ // the rest of the bit-stream contains the upper-band
+ // bit-stream curently this is the only thing there,
+ // however, we might add more layers.
+
+ // Have to exclude one byte where the length is stored
+ // and last 'LEN_CHECK_SUM_WORD8' bytes where the
+ // checksum is stored.
+ lenNextStream -= (LEN_CHECK_SUM_WORD8 + 1);
+
+ memcpy(decInstUB->bitstr_obj.stream,
+ &ptrEncodedUW8[numDecodedBytesLB + 1], lenNextStream);
+
+ // THIS IS THE FIRST DECODING
+ decInstUB->bitstr_obj.W_upper = 0xFFFFFFFF;
+ decInstUB->bitstr_obj.streamval = 0;
+ decInstUB->bitstr_obj.stream_index = 0;
+
+ // Decode jitter infotmation
+ err = WebRtcIsac_DecodeJitterInfo(&decInstUB->bitstr_obj,
+ &maxDelayBit);
+ // error check
+ if(err < 0)
+ {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+
+ // Update jitter info which is in the upper-band bit-stream
+ // only if the encoder is in super-wideband. Otherwise,
+ // the jitter info is already embeded in bandwidth index
+ // and has been updated.
+ if(instISAC->encoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ err = WebRtcIsac_UpdateUplinkJitter(
+ &(instISAC->bwestimator_obj), maxDelayBit);
+ if(err < 0)
+ {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+ }
+
+ // decode bandwidth information
+ err = WebRtcIsac_DecodeBandwidth(&decInstUB->bitstr_obj,
+ &bandwidthKHz);
+ if(err < 0)
+ {
+ instISAC->errorCode = -err;
+ return -1;
+ }
+
+ switch(bandwidthKHz)
+ {
+ case isac12kHz:
+ {
+ numDecodedBytesUB = WebRtcIsac_DecodeUb12(outFrame,
+ decInstUB, isRCUPayload);
+
+ // Hang-over for transient alleviation -
+ // wait two frames to add the upper band going up from 8 kHz
+ if (instISAC->resetFlag_8kHz > 0)
+ {
+ if (instISAC->resetFlag_8kHz == 2)
+ {
+ // Silence first and a half frame
+ memset(outFrame, 0, MAX_FRAMESAMPLES *
+ sizeof(float));
+ }
+ else
+ {
+ const float rampStep = 2.0f / MAX_FRAMESAMPLES;
+ float rampVal = 0;
+ memset(outFrame, 0, (MAX_FRAMESAMPLES>>1) *
+ sizeof(float));
+
+ // Ramp up second half of second frame
+ for(k = MAX_FRAMESAMPLES/2; k < MAX_FRAMESAMPLES; k++)
+ {
+ outFrame[k] *= rampVal;
+ rampVal += rampStep;
+ }
+ }
+ instISAC->resetFlag_8kHz -= 1;
+ }
+
+ break;
+ }
+ case isac16kHz:
+ {
+ numDecodedBytesUB = WebRtcIsac_DecodeUb16(outFrame,
+ decInstUB, isRCUPayload);
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ // it might be less due to garbage.
+ if((numDecodedBytesUB != lenNextStream) &&
+ (numDecodedBytesUB != (lenNextStream - ptrEncodedUW8[
+ numDecodedBytesLB + 1 + numDecodedBytesUB])))
+ {
+ instISAC->errorCode = ISAC_LENGTH_MISMATCH;
+ return -1;
+ }
+
+ // If there is no error Upper-band always decodes
+ // 30 ms (480 samples)
+ numSamplesUB = FRAMESAMPLES;
+
+ // Convert to W16
+ for(k = 0; k < numSamplesUB; k++)
+ {
+ if(outFrame[k] > 32767)
+ {
+ outFrameUB[k] = 32767;
+ }
+ else if(outFrame[k] < -32768)
+ {
+ outFrameUB[k] = -32768;
+ }
+ else
+ {
+ outFrameUB[k] = (WebRtc_Word16)WebRtcIsac_lrint(
+ outFrame[k]);
+ }
+ }
+ }
+ }
+
+ speechIdx = 0;
+ while(speechIdx < numSamplesLB)
+ {
+ WebRtcSpl_SynthesisQMF(&outFrameLB[speechIdx],
+ &outFrameUB[speechIdx], &decoded[(speechIdx<<1)],
+ instISAC->synthesisFBState1, instISAC->synthesisFBState2);
+
+ speechIdx += FRAMESAMPLES_10ms;
+ }
+ }
+ *speechType = 0;
+ return (numSamplesLB + numSamplesUB);
+}
+
+
+
+
+
+
+
+/****************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes a ISAC frame. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the frameSize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+WebRtc_Word16 WebRtcIsac_Decode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word16 lenEncodedBytes,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType)
+{
+ WebRtc_Word16 isRCUPayload = 0;
+ return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+ speechType, isRCUPayload);
+}
+
+/****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload i case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC RCU frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+
+
+
+WebRtc_Word16 WebRtcIsac_DecodeRcu(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word16 lenEncodedBytes,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType)
+{
+ WebRtc_Word16 isRCUPayload = 1;
+ return Decode(ISAC_main_inst, encoded, lenEncodedBytes, decoded,
+ speechType, isRCUPayload);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the frameSize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames to produce
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_DecodePlc(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16 noOfLostFrames)
+{
+ WebRtc_Word16 numSamples;
+ ISACMainStruct* instISAC;
+
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ /* Limit number of frames to two = 60 msec. Otherwise we exceed data vectors */
+ if(noOfLostFrames > 2)
+ {
+ noOfLostFrames = 2;
+ }
+
+ /* Get the number of samples per frame */
+ switch(instISAC->decoderSamplingRateKHz)
+ {
+ case kIsacWideband:
+ {
+ numSamples = 480 * noOfLostFrames;
+ break;
+ }
+ case kIsacSuperWideband:
+ {
+ numSamples = 960 * noOfLostFrames;
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ /* Set output samples to zero */
+ memset(decoded, 0, numSamples * sizeof(WebRtc_Word16));
+ return numSamples;
+}
+
+
+/****************************************************************************
+ * ControlLb(...) - Internal function for controling Lower Band
+ * ControlUb(...) - Internal function for controling Upper Band
+ * WebRtcIsac_Control(...) - API function
+ *
+ * This function sets the limit on the short-term average bit rate and the
+ * frame length. Should be used only in Instantaneous mode.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second (between 10000 and 32000)
+ * - frameSize : number of milliseconds per frame (30 or 60)
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+static WebRtc_Word16 ControlLb(
+ ISACLBStruct* instISAC,
+ double rate,
+ WebRtc_Word16 frameSize)
+{
+ if((rate >= 10000) && (rate <= 32000))
+ {
+ instISAC->ISACencLB_obj.bottleneck = rate;
+ }
+ else
+ {
+ return -ISAC_DISALLOWED_BOTTLENECK;
+ }
+
+ if((frameSize == 30) || (frameSize == 60))
+ {
+ instISAC->ISACencLB_obj.new_framelength = (FS/1000) * frameSize;
+ }
+ else
+ {
+ return -ISAC_DISALLOWED_FRAME_LENGTH;
+ }
+
+ return 0;
+}
+
+static WebRtc_Word16 ControlUb(
+ ISACUBStruct* instISAC,
+ double rate)
+{
+ if((rate >= 10000) && (rate <= 32000))
+ {
+ instISAC->ISACencUB_obj.bottleneck = rate;
+ }
+ else
+ {
+ return -ISAC_DISALLOWED_BOTTLENECK;
+ }
+ return 0;
+}
+
+WebRtc_Word16 WebRtcIsac_Control(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 bottleneckBPS,
+ WebRtc_Word16 frameSize)
+{
+ ISACMainStruct *instISAC;
+ WebRtc_Word16 status;
+ double rateLB;
+ double rateUB;
+ enum ISACBandwidth bandwidthKHz;
+
+
+ /* Typecast pointer to real structure */
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if(instISAC->codingMode == 0)
+ {
+ /* in adaptive mode */
+ instISAC->errorCode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if(instISAC->encoderSamplingRateKHz == kIsacWideband)
+ {
+ // if the sampling rate is 16kHz then bandwith should be 8kHz,
+ // regardless of bottleneck.
+ bandwidthKHz = isac8kHz;
+ rateLB = (bottleneckBPS > 32000)? 32000:bottleneckBPS;
+ rateUB = 0;
+ }
+ else
+ {
+ if(WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB,
+ &bandwidthKHz) < 0)
+ {
+ return -1;
+ }
+ }
+
+ if((instISAC->encoderSamplingRateKHz == kIsacSuperWideband) &&
+ (frameSize != 30) &&
+ (bandwidthKHz != isac8kHz))
+ {
+ // Cannot have 60 ms in super-wideband
+ instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+
+ status = ControlLb(&instISAC->instLB, rateLB, frameSize);
+ if(status < 0)
+ {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ if(bandwidthKHz != isac8kHz)
+ {
+ status = ControlUb(&(instISAC->instUB), rateUB);
+ if(status < 0)
+ {
+ instISAC->errorCode = -status;
+ return -1;
+ }
+ }
+
+ //
+ // Check if bandwidth is changing from wideband to super-wideband
+ // then we have to synch data buffer of lower & upper-band. also
+ // clean up the upper-band data buffer.
+ //
+ if((instISAC->bandwidthKHz == isac8kHz) &&
+ (bandwidthKHz != isac8kHz))
+ {
+ memset(instISAC->instUB.ISACencUB_obj.data_buffer_float, 0,
+ sizeof(float) * (MAX_FRAMESAMPLES + LB_TOTAL_DELAY_SAMPLES));
+
+ if(bandwidthKHz == isac12kHz)
+ {
+ instISAC->instUB.ISACencUB_obj.buffer_index =
+ instISAC->instLB.ISACencLB_obj.buffer_index;
+ }
+ else
+ {
+ instISAC->instUB.ISACencUB_obj.buffer_index = LB_TOTAL_DELAY_SAMPLES +
+ instISAC->instLB.ISACencLB_obj.buffer_index;
+
+ memcpy(&(instISAC->instUB.ISACencUB_obj.lastLPCVec),
+ WebRtcIsac_kMeanLarUb16, sizeof(double) * UB_LPC_ORDER);
+ }
+ }
+
+ // update the payload limit it the bandwidth is changing.
+ if(instISAC->bandwidthKHz != bandwidthKHz)
+ {
+ instISAC->bandwidthKHz = bandwidthKHz;
+ UpdatePayloadSizeLimit(instISAC);
+ }
+ instISAC->bottleneck = bottleneckBPS;
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Through this API, users can
+ * enforce a frame-size for all values of bottleneck. Then iSAC will not
+ * automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 32000 is accepted
+ * For default bottleneck set rateBPS = 0
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through out
+ * the adaptation process, 0 to let iSAC change
+ * the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+WebRtc_Word16 WebRtcIsac_ControlBwe(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 bottleneckBPS,
+ WebRtc_Word16 frameSizeMs,
+ WebRtc_Word16 enforceFrameSize)
+{
+ ISACMainStruct *instISAC;
+ enum ISACBandwidth bandwidth;
+
+ /* Typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Check that we are in channel-adaptive mode, otherwise, return (-1) */
+ if(instISAC->codingMode != 0)
+ {
+ instISAC->errorCode = ISAC_MODE_MISMATCH;
+ return -1;
+ }
+ if((frameSizeMs != 30) &&
+ (instISAC->encoderSamplingRateKHz == kIsacSuperWideband))
+ {
+ return -1;
+ }
+
+ /* Set struct variable if enforceFrameSize is set. ISAC will then */
+ /* keep the chosen frame size. */
+ if((enforceFrameSize != 0) /*||
+ (instISAC->samplingRateKHz == kIsacSuperWideband)*/)
+ {
+ instISAC->instLB.ISACencLB_obj.enforceFrameSize = 1;
+ }
+ else
+ {
+ instISAC->instLB.ISACencLB_obj.enforceFrameSize = 0;
+ }
+
+ /* Set initial rate, if value between 10000 and 32000, */
+ /* if rateBPS is 0, keep the default initial bottleneck value (15000) */
+ if(bottleneckBPS != 0)
+ {
+ double rateLB;
+ double rateUB;
+ if(WebRtcIsac_RateAllocation(bottleneckBPS, &rateLB, &rateUB, &bandwidth) < 0)
+ {
+ return -1;
+ }
+ instISAC->bwestimator_obj.send_bw_avg = (float)bottleneckBPS;
+ instISAC->bandwidthKHz = bandwidth;
+ }
+
+ /* Set initial frameSize. If enforceFrameSize is set the frame size will
+ not change */
+ if(frameSizeMs != 0)
+ {
+ if((frameSizeMs == 30) || (frameSizeMs == 60))
+ {
+ instISAC->instLB.ISACencLB_obj.new_framelength = (FS/1000) *
+ frameSizeMs;
+ //instISAC->bwestimator_obj.rec_header_rate = ((float)HEADER_SIZE *
+ // 8.0f * 1000.0f / (float)frameSizeMs);
+ }
+ else
+ {
+ instISAC->errorCode = ISAC_DISALLOWED_FRAME_LENGTH;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - bweIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+WebRtc_Word16 WebRtcIsac_GetDownLinkBwIndex(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* bweIndex,
+ WebRtc_Word16* jitterInfo)
+{
+ ISACMainStruct *instISAC;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_DEC_INIT) !=
+ BIT_MASK_DEC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Call function to get Bandwidth Estimate */
+ WebRtcIsac_GetDownlinkBwJitIndexImpl(&(instISAC->bwestimator_obj),
+ bweIndex, jitterInfo, instISAC->decoderSamplingRateKHz);
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ * - rateIndex : Bandwidth estimate from other side.
+ *
+ * Return value : 0 - ok
+ * -1 - index out of range
+ */
+WebRtc_Word16 WebRtcIsac_UpdateUplinkBw(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 bweIndex)
+{
+ ISACMainStruct *instISAC;
+ WebRtc_Word16 returnVal;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ /* Call function to get Bandwidth Estimate */
+ returnVal = WebRtcIsac_UpdateUplinkBwImpl(
+ &(instISAC->bwestimator_obj), bweIndex,
+ instISAC->encoderSamplingRateKHz);
+
+ if(returnVal < 0)
+ {
+ instISAC->errorCode = -returnVal;
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the
+ * bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - bweIndex : Bandwidth estimate in bitstream
+ *
+ */
+WebRtc_Word16 WebRtcIsac_ReadBwIndex(
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* bweIndex)
+{
+ Bitstr streamdata;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for(k = 0; k < 10; k++)
+ {
+ streamdata.stream[k] = (WebRtc_UWord8) ((encoded[k>>1] >>
+ ((k&1) << 3)) & 0xFF);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ /* decode frame length */
+ err = WebRtcIsac_DecodeFrameLen(&streamdata, bweIndex);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ /* decode BW estimation */
+ err = WebRtcIsac_DecodeSendBW(&streamdata, bweIndex);
+ if(err < 0)
+ {
+ return err;
+ }
+
+ return 0;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+WebRtc_Word16 WebRtcIsac_ReadFrameLen(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* frameLength)
+{
+ Bitstr streamdata;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+ WebRtc_Word16 err;
+ ISACMainStruct* instISAC;
+
+ streamdata.W_upper = 0xFFFFFFFF;
+ streamdata.streamval = 0;
+ streamdata.stream_index = 0;
+
+#ifndef WEBRTC_BIG_ENDIAN
+ for (k=0; k<10; k++) {
+ streamdata.stream[k] = (WebRtc_UWord8) ((encoded[k>>1] >>
+ ((k&1) << 3)) & 0xFF);
+ }
+#else
+ memcpy(streamdata.stream, encoded, 10);
+#endif
+
+ /* decode frame length */
+ err = WebRtcIsac_DecodeFrameLen(&streamdata, frameLength);
+ if(err < 0) {
+ return -1;
+ }
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if(instISAC->decoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ // the decoded frame length indicates the number of samples in
+ // lower-band in this case, multiply by 2 to get the total number
+ // of samples.
+ *frameLength <<= 1;
+ }
+
+ return 0;
+}
+
+
+/*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * returns the frame lenght (in samples) of the next packet. In the case of
+ * channel-adaptive mode, iSAC decides on its frame lenght based on the
+ * estimated bottleneck this allows a user to prepare for the next packet
+ * (at the encoder).
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Return Value : frame lenght in samples
+ *
+ */
+WebRtc_Word16 WebRtcIsac_GetNewFrameLen(
+ ISACStruct *ISAC_main_inst)
+{
+ ISACMainStruct *instISAC;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* Return new frame length */
+ if(instISAC->encoderSamplingRateKHz == kIsacWideband)
+ {
+ return (instISAC->instLB.ISACencLB_obj.new_framelength);
+ }
+ else
+ {
+ return ((instISAC->instLB.ISACencLB_obj.new_framelength) << 1);
+ }
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance.
+ * When a function returns -1 a error code will be set for that instance.
+ * The function below extract the code of the last error that occured in
+ * the specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+WebRtc_Word16 WebRtcIsac_GetErrorCode(
+ ISACStruct *ISAC_main_inst)
+{
+ ISACMainStruct *instISAC;
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ return (instISAC->errorCode);
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through in-band
+ * signalling retreived by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...) (if
+ * xxx_control is never called the default values is).
+ * Note that the output is the iSAC internal operating bottleneck whch might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Output:
+ * - *bottleneck : bottleneck in bits/sec
+ *
+ * Return value : -1 if error happens
+ * 0 bit-rates computed correctly.
+ */
+WebRtc_Word16 WebRtcIsac_GetUplinkBw(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32* bottleneck)
+{
+ ISACMainStruct* instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ if(instISAC->codingMode == 0)
+ {
+ // we are in adaptive mode then get the bottleneck from BWE
+ *bottleneck = (WebRtc_Word32)instISAC->bwestimator_obj.send_bw_avg;
+ }
+ else
+ {
+ *bottleneck = instISAC->bottleneck;
+ }
+
+ if((*bottleneck > 32000) && (*bottleneck < 38000))
+ {
+ *bottleneck = 32000;
+ }
+ else if((*bottleneck > 45000) && (*bottleneck < 50000))
+ {
+ *bottleneck = 45000;
+ }
+ else if(*bottleneck > 56000)
+ {
+ *bottleneck = 56000;
+ }
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 100 and 400 bytes
+ * if encoder sampling rate is 16 kHz. For
+ * 32 kHz encoder sampling rate valid values
+ * are between 100 and 600 bytes.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+WebRtc_Word16 WebRtcIsac_SetMaxPayloadSize(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 maxPayloadBytes)
+{
+ ISACMainStruct *instISAC;
+ WebRtc_Word16 status = 0;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+
+ if(instISAC->encoderSamplingRateKHz == kIsacSuperWideband)
+ {
+ // sanity check
+ if(maxPayloadBytes < 120)
+ {
+ // maxRate is out of valid range
+ // set to the acceptable value and return -1.
+ maxPayloadBytes = 120;
+ status = -1;
+ }
+
+ /* sanity check */
+ if(maxPayloadBytes > STREAM_SIZE_MAX)
+ {
+ // maxRate is out of valid range
+ // set to the acceptable value and return -1.
+ maxPayloadBytes = STREAM_SIZE_MAX;
+ status = -1;
+ }
+ }
+ else
+ {
+ if(maxPayloadBytes < 120)
+ {
+ // max payload-size is out of valid range
+ // set to the acceptable value and return -1.
+ maxPayloadBytes = 120;
+ status = -1;
+ }
+ if(maxPayloadBytes > STREAM_SIZE_MAX_60)
+ {
+ // max payload-size is out of valid range
+ // set to the acceptable value and return -1.
+ maxPayloadBytes = STREAM_SIZE_MAX_60;
+ status = -1;
+ }
+ }
+ instISAC->maxPayloadSizeBytes = maxPayloadBytes;
+ UpdatePayloadSizeLimit(instISAC);
+ return status;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRate : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits/sec in
+ * wideband mode, and 32000 to 160000 bits/sec in
+ * super-wideband mode.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+WebRtc_Word16 WebRtcIsac_SetMaxRate(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 maxRate)
+{
+ ISACMainStruct *instISAC;
+ WebRtc_Word16 maxRateInBytesPer30Ms;
+ WebRtc_Word16 status = 0;
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct *)ISAC_main_inst;
+
+ /* check if encoder initiated */
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ return -1;
+ }
+ /*
+ Calculate maximum number of bytes per 30 msec packets for the
+ given maximum rate. Multiply with 30/1000 to get number of
+ bits per 30 ms, divide by 8 to get number of bytes per 30 ms:
+ maxRateInBytes = floor((maxRate * 30/1000) / 8);
+ */
+ maxRateInBytesPer30Ms = (WebRtc_Word16)(maxRate*3/800);
+
+ if(instISAC->encoderSamplingRateKHz == kIsacWideband)
+ {
+ if(maxRate < 32000)
+ {
+ // max rate is out of valid range
+ // set to the acceptable value and return -1.
+ maxRateInBytesPer30Ms = 120;
+ status = -1;
+ }
+
+ if(maxRate > 53400)
+ {
+ // max rate is out of valid range
+ // set to the acceptable value and return -1.
+ maxRateInBytesPer30Ms = 200;
+ status = -1;
+ }
+ }
+ else
+ {
+ if(maxRateInBytesPer30Ms < 120)
+ {
+ // maxRate is out of valid range
+ // set to the acceptable value and return -1.
+ maxRateInBytesPer30Ms = 120;
+ status = -1;
+ }
+
+ if(maxRateInBytesPer30Ms > STREAM_SIZE_MAX)
+ {
+ // maxRate is out of valid range
+ // set to the acceptable value and return -1.
+ maxRateInBytesPer30Ms = STREAM_SIZE_MAX;
+ status = -1;
+ }
+ }
+ instISAC->maxRateBytesPer30Ms = maxRateInBytesPer30Ms;
+ UpdatePayloadSizeLimit(instISAC);
+ return status;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * Populates "encoded" with the redundant payload of the recently encoded
+ * frame. This function has to be called once that WebRtcIsac_Encode(...)
+ * returns a positive value. Regardless of the frame-size this function will
+ * be called only once after encoding is completed. The bit-stream is
+ * targeted for 16000 bit/sec.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ *
+ *
+ */
+WebRtc_Word16 WebRtcIsac_GetRedPayload(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* encoded)
+{
+ ISACMainStruct* instISAC;
+ Bitstr iSACBitStreamInst;
+ WebRtc_Word16 streamLenLB;
+ WebRtc_Word16 streamLenUB;
+ WebRtc_Word16 streamLen;
+ WebRtc_Word16 totalLenUB;
+ WebRtc_UWord8* ptrEncodedUW8 = (WebRtc_UWord8*)encoded;
+#ifndef WEBRTC_BIG_ENDIAN
+ int k;
+#endif
+
+ /* typecast pointer to real structure */
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+
+ if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ instISAC->errorCode = ISAC_ENCODER_NOT_INITIATED;
+ }
+
+
+ iSACBitStreamInst.W_upper = 0xFFFFFFFF;
+ iSACBitStreamInst.streamval = 0;
+ iSACBitStreamInst.stream_index = 0;
+
+
+ streamLenLB = WebRtcIsac_EncodeStoredDataLb(
+ &instISAC->instLB.ISACencLB_obj.SaveEnc_obj,
+ &iSACBitStreamInst,
+ instISAC->instLB.ISACencLB_obj.lastBWIdx,
+ RCU_TRANSCODING_SCALE);
+
+ if(streamLenLB < 0)
+ {
+ return -1;
+ }
+
+ /* convert from bytes to WebRtc_Word16 */
+ memcpy(ptrEncodedUW8, iSACBitStreamInst.stream, streamLenLB);
+
+ streamLen = streamLenLB;
+
+ if(instISAC->bandwidthKHz == isac8kHz)
+ {
+ return streamLenLB;
+ }
+
+ streamLenUB = WebRtcIsac_GetRedPayloadUb(
+ &instISAC->instUB.ISACencUB_obj.SaveEnc_obj,
+ &iSACBitStreamInst, instISAC->bandwidthKHz);
+
+ if(streamLenUB < 0)
+ {
+ // an error has happened but this is not the error due to a
+ // bit-stream larger than the limit
+ return -1;
+ }
+
+ // We have one byte to write the total length of the upper band
+ // the length include the bitstream length, check-sum and the
+ // single byte where the length is written to. This is according to
+ // iSAC wideband and how the "garbage" is dealt.
+ totalLenUB = streamLenUB + 1 + LEN_CHECK_SUM_WORD8;
+ if(totalLenUB > 255)
+ {
+ streamLenUB = 0;
+ }
+
+ // Generate CRC if required.
+ if((instISAC->bandwidthKHz != isac8kHz) &&
+ (streamLenUB > 0))
+ {
+ WebRtc_UWord32 crc;
+ streamLen += totalLenUB;
+ ptrEncodedUW8[streamLenLB] = (WebRtc_UWord8)totalLenUB;
+ memcpy(&ptrEncodedUW8[streamLenLB+1], iSACBitStreamInst.stream, streamLenUB);
+
+ WebRtcIsac_GetCrc((WebRtc_Word16*)(&(ptrEncodedUW8[streamLenLB + 1])),
+ streamLenUB, &crc);
+#ifndef WEBRTC_BIG_ENDIAN
+ for(k = 0; k < LEN_CHECK_SUM_WORD8; k++)
+ {
+ ptrEncodedUW8[streamLen - LEN_CHECK_SUM_WORD8 + k] =
+ (WebRtc_UWord8)((crc >> (24 - k * 8)) & 0xFF);
+ }
+#else
+ memcpy(&ptrEncodedUW8[streamLenLB + streamLenUB + 1], &crc,
+ LEN_CHECK_SUM_WORD8);
+#endif
+ }
+
+
+ return streamLen;
+}
+
+
+/****************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+void WebRtcIsac_version(char *version)
+{
+ strcpy(version, "4.3.0");
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * Set the sampling rate of the encoder. Initialization of the encoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created. The encoding-mode and the
+ * bottleneck remain unchanged by this call, however, the maximum rate and
+ * maximum payload-size will reset to their default value.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_SetEncSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if((sampRate != kIsacWideband) &&
+ (sampRate != kIsacSuperWideband))
+ {
+ // Sampling Frequency is not supported
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ }
+ else if((instISAC->initFlag & BIT_MASK_ENC_INIT) !=
+ BIT_MASK_ENC_INIT)
+ {
+ if(sampRate == kIsacWideband)
+ {
+ instISAC->bandwidthKHz = isac8kHz;
+ }
+ else
+ {
+ instISAC->bandwidthKHz = isac16kHz;
+ }
+ instISAC->encoderSamplingRateKHz = sampRate;
+ return 0;
+ }
+ else
+ {
+ ISACUBStruct* instUB = &(instISAC->instUB);
+ ISACLBStruct* instLB = &(instISAC->instLB);
+ double bottleneckLB;
+ double bottleneckUB;
+ WebRtc_Word32 bottleneck = instISAC->bottleneck;
+ WebRtc_Word16 codingMode = instISAC->codingMode;
+ WebRtc_Word16 frameSizeMs = instLB->ISACencLB_obj.new_framelength / (FS / 1000);
+
+ if((sampRate == kIsacWideband) &&
+ (instISAC->encoderSamplingRateKHz == kIsacSuperWideband))
+ {
+ // changing from super-wideband to wideband.
+ // we don't need to re-initialize the encoder of the
+ // lower-band.
+ instISAC->bandwidthKHz = isac8kHz;
+ if(codingMode == 1)
+ {
+ ControlLb(instLB,
+ (bottleneck > 32000)? 32000:bottleneck, FRAMESIZE);
+ }
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX_60;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX_30;
+ }
+ else if((sampRate == kIsacSuperWideband) &&
+ (instISAC->encoderSamplingRateKHz == kIsacWideband))
+ {
+ if(codingMode == 1)
+ {
+ WebRtcIsac_RateAllocation(bottleneck, &bottleneckLB, &bottleneckUB,
+ &(instISAC->bandwidthKHz));
+ }
+
+ instISAC->bandwidthKHz = isac16kHz;
+ instISAC->maxPayloadSizeBytes = STREAM_SIZE_MAX;
+ instISAC->maxRateBytesPer30Ms = STREAM_SIZE_MAX;
+
+ EncoderInitLb(instLB, codingMode, sampRate);
+ EncoderInitUb(instUB, instISAC->bandwidthKHz);
+
+ memset(instISAC->analysisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+ memset(instISAC->analysisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+
+ if(codingMode == 1)
+ {
+ instISAC->bottleneck = bottleneck;
+ ControlLb(instLB, bottleneckLB,
+ (instISAC->bandwidthKHz == isac8kHz)? frameSizeMs:FRAMESIZE);
+ if(instISAC->bandwidthKHz > isac8kHz)
+ {
+ ControlUb(instUB, bottleneckUB);
+ }
+ }
+ else
+ {
+ instLB->ISACencLB_obj.enforceFrameSize = 0;
+ instLB->ISACencLB_obj.new_framelength = FRAMESAMPLES;
+ }
+ }
+ instISAC->encoderSamplingRateKHz = sampRate;
+ return 0;
+ }
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * Set the sampling rate of the decoder. Initialization of the decoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+WebRtc_Word16 WebRtcIsac_SetDecSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ if((sampRate != kIsacWideband) &&
+ (sampRate != kIsacSuperWideband))
+ {
+ // Sampling Frequency is not supported
+ instISAC->errorCode = ISAC_UNSUPPORTED_SAMPLING_FREQUENCY;
+ return -1;
+ }
+ else
+ {
+ if((instISAC->decoderSamplingRateKHz == kIsacWideband) &&
+ (sampRate == kIsacSuperWideband))
+ {
+ // switching from wideband to super-wideband at the decoder
+ // we need to reset the filter-bank and initialize
+ // upper-band decoder.
+ memset(instISAC->synthesisFBState1, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+ memset(instISAC->synthesisFBState2, 0,
+ FB_STATE_SIZE_WORD32 * sizeof(WebRtc_Word32));
+
+ if(DecoderInitUb(&(instISAC->instUB)) < 0)
+ {
+ return -1;
+ }
+ }
+ instISAC->decoderSamplingRateKHz = sampRate;
+ return 0;
+ }
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the encoder, the input audio
+ * is expected to be sampled at this rate.
+ *
+ */
+enum IsacSamplingRate WebRtcIsac_EncSampRate(
+ ISACStruct* ISAC_main_inst)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ return instISAC->encoderSamplingRateKHz;
+}
+
+
+/******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the decoder, i.e. the
+ * sampling rate of the decoded audio.
+ *
+ */
+enum IsacSamplingRate WebRtcIsac_DecSampRate(
+ ISACStruct* ISAC_main_inst)
+{
+ ISACMainStruct* instISAC;
+
+ instISAC = (ISACMainStruct*)ISAC_main_inst;
+
+ return instISAC->decoderSamplingRateKHz;
+}
diff --git a/src/mod/codecs/mod_isac/isac.gypi b/src/mod/codecs/mod_isac/isac.gypi
new file mode 100644
index 0000000000..d30be551bd
--- /dev/null
+++ b/src/mod/codecs/mod_isac/isac.gypi
@@ -0,0 +1,91 @@
+# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'iSAC',
+ 'type': '<(library)',
+ 'dependencies': [
+ '<(webrtc_root)/common_audio/common_audio.gyp:signal_processing',
+ ],
+ 'include_dirs': [
+ '../interface',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '../interface',
+ ],
+ },
+ 'sources': [
+ '../interface/isac.h',
+ 'arith_routines.c',
+ 'arith_routines_hist.c',
+ 'arith_routines_logist.c',
+ 'bandwidth_estimator.c',
+ 'crc.c',
+ 'decode.c',
+ 'decode_bwe.c',
+ 'encode.c',
+ 'encode_lpc_swb.c',
+ 'entropy_coding.c',
+ 'fft.c',
+ 'filter_functions.c',
+ 'filterbank_tables.c',
+ 'intialize.c',
+ 'isac.c',
+ 'filterbanks.c',
+ 'pitch_lag_tables.c',
+ 'lattice.c',
+ 'lpc_gain_swb_tables.c',
+ 'lpc_analysis.c',
+ 'lpc_shape_swb12_tables.c',
+ 'lpc_shape_swb16_tables.c',
+ 'lpc_tables.c',
+ 'pitch_estimator.c',
+ 'pitch_filter.c',
+ 'pitch_gain_tables.c',
+ 'spectrum_ar_model_tables.c',
+ 'transform.c',
+ 'arith_routines.h',
+ 'bandwidth_estimator.h',
+ 'codec.h',
+ 'crc.h',
+ 'encode_lpc_swb.h',
+ 'entropy_coding.h',
+ 'fft.h',
+ 'filterbank_tables.h',
+ 'lpc_gain_swb_tables.h',
+ 'lpc_analysis.h',
+ 'lpc_shape_swb12_tables.h',
+ 'lpc_shape_swb16_tables.h',
+ 'lpc_tables.h',
+ 'pitch_estimator.h',
+ 'pitch_gain_tables.h',
+ 'pitch_lag_tables.h',
+ 'settings.h',
+ 'spectrum_ar_model_tables.h',
+ 'structs.h',
+ 'os_specific_inline.h',
+ ],
+ 'conditions': [
+ ['OS!="win"', {
+ 'defines': [
+ 'WEBRTC_LINUX',
+ ],
+ }],
+ ],
+ },
+ ],
+}
+
+# Local Variables:
+# tab-width:2
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/src/mod/codecs/mod_isac/isac.h b/src/mod/codecs/mod_isac/isac.h
new file mode 100644
index 0000000000..03c260bb8a
--- /dev/null
+++ b/src/mod/codecs/mod_isac/isac.h
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_
+
+/*
+ * Define the fixed-point numeric formats
+ */
+#include "typedefs.h"
+
+typedef struct WebRtcISACStruct ISACStruct;
+
+enum IsacSamplingRate {kIsacWideband = 16, kIsacSuperWideband = 32};
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+ /******************************************************************************
+ * WebRtcIsac_AssignSize(...)
+ *
+ * This function returns the size of the ISAC instance, so that the instance
+ * can be created outside iSAC.
+ *
+ * Input:
+ * - samplingRate : sampling rate of the input/output audio.
+ *
+ * Output:
+ * - sizeinbytes : number of bytes needed to allocate for the
+ * instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_AssignSize(
+ int* sizeinbytes);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Assign(...)
+ *
+ * This function assignes the memory already created to the ISAC instance.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ * - samplingRate : sampling rate of the input/output audio.
+ * - ISAC_inst_Addr : the already allocated memory, where we put the
+ * iSAC structure.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Assign(
+ ISACStruct** ISAC_main_inst,
+ void* ISAC_inst_Addr);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Create(...)
+ *
+ * This function creates an ISAC instance, which will contain the state
+ * information for one coding/decoding channel.
+ *
+ * Input:
+ * - *ISAC_main_inst : a pointer to the coder instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Create(
+ ISACStruct** ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Free(...)
+ *
+ * This function frees the ISAC instance created at the beginning.
+ *
+ * Input:
+ * - ISAC_main_inst : an ISAC instance.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Free(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_EncoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the encoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - CodingMode : 0 -> Bit rate and frame length are
+ * automatically adjusted to available bandwidth
+ * on transmission channel, just valid if codec
+ * is created to work in wideband mode.
+ * 1 -> User sets a frame length and a target bit
+ * rate which is taken as the maximum
+ * short-term average bit rate.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_EncoderInit(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 CodingMode);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Encode(...)
+ *
+ * This function encodes 10ms audio blocks and inserts it into a package.
+ * Input speech length has 160 samples if operating at 16 kHz sampling
+ * rate, or 320 if operating at 32 kHz sampling rate. The encoder buffers the
+ * input audio until the whole frame is buffered then proceeds with encoding.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - speechIn : input speech vector.
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : 0 - The buffer didn't reach the chosen
+ * frame-size so it keeps buffering speech
+ * samples.
+ * : -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Encode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* speechIn,
+ WebRtc_Word16* encoded);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecoderInit(...)
+ *
+ * This function initializes an ISAC instance prior to the decoder calls.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ *
+ * Return value
+ * : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_DecoderInit(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_UpdateBwEstimate(...)
+ *
+ * This function updates the estimate of the bandwidth.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - packet_size : size of the packet.
+ * - rtp_seq_number : the RTP number of the packet.
+ * - send_ts : the RTP send timestamp, given in samples
+ * - arr_ts : the arrival time of the packet (from NetEq)
+ * in samples.
+ *
+ * Return value : 0 - Ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_UpdateBwEstimate(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word32 packet_size,
+ WebRtc_UWord16 rtp_seq_number,
+ WebRtc_UWord32 send_ts,
+ WebRtc_UWord32 arr_ts);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Decode(...)
+ *
+ * This function decodes an ISAC frame. At 16 kHz sampling rate, the length
+ * of the output audio could be either 480 or 960 samples, equivalent to
+ * 30 or 60 ms respectively. At 32 kHz sampling rate, the length of the
+ * output audio is 960 samples, which is 30 ms.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC frame(s).
+ * - len : bytes in encoded vector.
+ *
+ * Output:
+ * - decoded : The decoded vector.
+ *
+ * Return value : >0 - number of samples in decoded vector.
+ * -1 - Error.
+ */
+
+ WebRtc_Word16 WebRtcIsac_Decode(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecodePlc(...)
+ *
+ * This function conducts PLC for ISAC frame(s). Output speech length
+ * will be a multiple of frames, i.e. multiples of 30 ms audio. Therefore,
+ * the output is multiple of 480 samples if operating at 16 kHz and multiple
+ * of 960 if operating at 32 kHz.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - noOfLostFrames : Number of PLC frames to produce.
+ *
+ * Output:
+ * - decoded : The decoded vector.
+ *
+ * Return value : >0 - number of samples in decoded PLC vector
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_DecodePlc(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16 noOfLostFrames);
+
+
+ /******************************************************************************
+ * WebRtcIsac_Control(...)
+ *
+ * This function sets the limit on the short-term average bit-rate and the
+ * frame length. Should be used only in Instantaneous mode. At 16 kHz sampling
+ * rate, an average bit-rate between 10000 to 32000 bps is valid and a
+ * frame-size of 30 or 60 ms is acceptable. At 32 kHz, an average bit-rate
+ * between 10000 to 56000 is acceptable, and the valid frame-size is 30 ms.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rate : limit on the short-term average bit rate,
+ * in bits/second.
+ * - framesize : frame-size in millisecond.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_Control(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 rate,
+ WebRtc_Word16 framesize);
+
+
+ /******************************************************************************
+ * WebRtcIsac_ControlBwe(...)
+ *
+ * This function sets the initial values of bottleneck and frame-size if
+ * iSAC is used in channel-adaptive mode. Therefore, this API is not
+ * applicable if the codec is created to operate in super-wideband mode.
+ *
+ * Through this API, users can enforce a frame-size for all values of
+ * bottleneck. Then iSAC will not automatically change the frame-size.
+ *
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - rateBPS : initial value of bottleneck in bits/second
+ * 10000 <= rateBPS <= 56000 is accepted
+ * For default bottleneck set rateBPS = 0
+ * - frameSizeMs : number of milliseconds per frame (30 or 60)
+ * - enforceFrameSize : 1 to enforce the given frame-size through
+ * out the adaptation process, 0 to let iSAC
+ * change the frame-size if required.
+ *
+ * Return value : 0 - ok
+ * -1 - Error
+ */
+
+ WebRtc_Word16 WebRtcIsac_ControlBwe(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 rateBPS,
+ WebRtc_Word16 frameSizeMs,
+ WebRtc_Word16 enforceFrameSize);
+
+
+ /******************************************************************************
+ * WebRtcIsac_ReadFrameLen(...)
+ *
+ * This function returns the length of the frame represented in the packet.
+ *
+ * Input:
+ * - encoded : Encoded bit-stream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_ReadFrameLen(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* frameLength);
+
+
+ /******************************************************************************
+ * WebRtcIsac_version(...)
+ *
+ * This function returns the version number.
+ *
+ * Output:
+ * - version : Pointer to character string
+ *
+ */
+
+ void WebRtcIsac_version(
+ char *version);
+
+
+ /******************************************************************************
+ * WebRtcIsac_GetErrorCode(...)
+ *
+ * This function can be used to check the error code of an iSAC instance. When
+ * a function returns -1 a error code will be set for that instance. The
+ * function below extract the code of the last error that occurred in the
+ * specified instance.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance
+ *
+ * Return value : Error code
+ */
+
+ WebRtc_Word16 WebRtcIsac_GetErrorCode(
+ ISACStruct* ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetUplinkBw(...)
+ *
+ * This function outputs the target bottleneck of the codec. In
+ * channel-adaptive mode, the target bottleneck is specified through in-band
+ * signalling retreived by bandwidth estimator.
+ * In channel-independent, also called instantaneous mode, the target
+ * bottleneck is provided to the encoder by calling xxx_control(...). If
+ * xxx_control is never called the default values is returned. The default
+ * value for bottleneck at 16 kHz encoder sampling rate is 32000 bits/sec,
+ * and it is 56000 bits/sec for 32 kHz sampling rate.
+ * Note that the output is the iSAC internal operating bottleneck which might
+ * differ slightly from the one provided through xxx_control().
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Output:
+ * - *bottleneck : bottleneck in bits/sec
+ *
+ * Return value : -1 if error happens
+ * 0 bit-rates computed correctly.
+ */
+
+ WebRtc_Word16 WebRtcIsac_GetUplinkBw(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32* bottleneck);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetMaxPayloadSize(...)
+ *
+ * This function sets a limit for the maximum payload size of iSAC. The same
+ * value is used both for 30 and 60 ms packets. If the encoder sampling rate
+ * is 16 kHz the maximum payload size is between 120 and 400 bytes. If the
+ * encoder sampling rate is 32 kHz the maximum payload size is between 120
+ * and 600 bytes.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, i.e. min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxPayloadBytes : maximum size of the payload in bytes
+ * valid values are between 120 and 400 bytes
+ * if encoder sampling rate is 16 kHz. For
+ * 32 kHz encoder sampling rate valid values
+ * are between 120 and 600 bytes.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetMaxPayloadSize(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 maxPayloadBytes);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetMaxRate(...)
+ *
+ * This function sets the maximum rate which the codec may not exceed for
+ * any signal packet. The maximum rate is defined and payload-size per
+ * frame-size in bits per second.
+ *
+ * The codec has a maximum rate of 53400 bits per second (200 bytes per 30
+ * ms) if the encoder sampling rate is 16kHz, and 160 kbps (600 bytes/30 ms)
+ * if the encoder sampling rate is 32 kHz.
+ *
+ * It is possible to set a maximum rate between 32000 and 53400 bits/sec
+ * in wideband mode, and 32000 to 160000 bits/sec in super-wideband mode.
+ *
+ * If an out of range limit is used, the function returns -1, but the closest
+ * valid value will be applied.
+ *
+ * ---------------
+ * IMPORTANT NOTES
+ * ---------------
+ * The size of a packet is limited to the minimum of 'max-payload-size' and
+ * 'max-rate.' For instance, let's assume the max-payload-size is set to
+ * 170 bytes, and max-rate is set to 40 kbps. Note that a limit of 40 kbps
+ * translates to 150 bytes for 30ms frame-size & 300 bytes for 60ms
+ * frame-size. Then a packet with a frame-size of 30 ms is limited to 150,
+ * i.e. min(170, 150), and a packet with 60 ms frame-size is limited to
+ * 170 bytes, min(170, 300).
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - maxRate : maximum rate in bits per second,
+ * valid values are 32000 to 53400 bits/sec in
+ * wideband mode, and 32000 to 160000 bits/sec in
+ * super-wideband mode.
+ *
+ * Return value : 0 if successful
+ * -1 if error happens
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetMaxRate(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word32 maxRate);
+
+
+ /******************************************************************************
+ * WebRtcIsac_DecSampRate()
+ * Return the sampling rate of the decoded audio.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the decoder, i.e. the
+ * sampling rate of the decoded audio.
+ *
+ */
+
+ enum IsacSamplingRate WebRtcIsac_DecSampRate(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_EncSampRate()
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ *
+ * Return value : enumerator representing sampling frequency
+ * associated with the encoder, the input audio
+ * is expected to be sampled at this rate.
+ *
+ */
+
+ enum IsacSamplingRate WebRtcIsac_EncSampRate(
+ ISACStruct* ISAC_main_inst);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetDecSampRate()
+ * Set the sampling rate of the decoder. Initialization of the decoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetDecSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate);
+
+
+ /******************************************************************************
+ * WebRtcIsac_SetEncSampRate()
+ * Set the sampling rate of the encoder. Initialization of the encoder WILL
+ * NOT overwrite the sampling rate of the encoder. The default value is 16 kHz
+ * which is set when the instance is created. The encoding-mode and the
+ * bottleneck remain unchanged by this call, however, the maximum rate and
+ * maximum payload-size will reset to their default value.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC instance
+ * - sampRate : enumerator specifying the sampling rate.
+ *
+ * Return value : 0 if successful
+ * -1 if failed.
+ */
+
+ WebRtc_Word16 WebRtcIsac_SetEncSampRate(
+ ISACStruct* ISAC_main_inst,
+ enum IsacSamplingRate sampRate);
+
+
+
+ /******************************************************************************
+ * WebRtcIsac_GetNewBitStream(...)
+ *
+ * This function returns encoded data, with the recieved bwe-index in the
+ * stream. If the rate is set to a value less than bottleneck of codec
+ * the new bistream will be re-encoded with the given target rate.
+ * It should always return a complete packet, i.e. only called once
+ * even for 60 msec frames.
+ *
+ * NOTE 1! This function does not write in the ISACStruct, it is not allowed.
+ * NOTE 2! Currently not implemented for SWB mode.
+ * NOTE 3! Rates larger than the bottleneck of the codec will be limited
+ * to the current bottleneck.
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - bweIndex : Index of bandwidth estimate to put in new
+ * bitstream
+ * - rate : target rate of the transcoder is bits/sec.
+ * Valid values are the accepted rate in iSAC,
+ * i.e. 10000 to 56000.
+ * - isRCU : if the new bit-stream is an RCU stream.
+ * Note that the rate parameter always indicates
+ * the target rate of the main paylaod, regardless
+ * of 'isRCU' value.
+ *
+ * Output:
+ * - encoded : The encoded data vector
+ *
+ * Return value : >0 - Length (in bytes) of coded data
+ * -1 - Error or called in SWB mode
+ * NOTE! No error code is written to
+ * the struct since it is only allowed to read
+ * the struct.
+ */
+ WebRtc_Word16 WebRtcIsac_GetNewBitStream(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 bweIndex,
+ WebRtc_Word16 jitterInfo,
+ WebRtc_Word32 rate,
+ WebRtc_Word16* encoded,
+ WebRtc_Word16 isRCU);
+
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetDownLinkBwIndex(...)
+ *
+ * This function returns index representing the Bandwidth estimate from
+ * other side to this side.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - bweIndex : Bandwidth estimate to transmit to other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_GetDownLinkBwIndex(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* bweIndex,
+ WebRtc_Word16* jitterInfo);
+
+
+ /****************************************************************************
+ * WebRtcIsac_UpdateUplinkBw(...)
+ *
+ * This function takes an index representing the Bandwidth estimate from
+ * this side to other side and updates BWE.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ * - bweIndex : Bandwidth estimate from other side.
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_UpdateUplinkBw(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16 bweIndex);
+
+
+ /****************************************************************************
+ * WebRtcIsac_ReadBwIndex(...)
+ *
+ * This function returns the index of the Bandwidth estimate from the bitstream.
+ *
+ * Input:
+ * - encoded : Encoded bitstream
+ *
+ * Output:
+ * - frameLength : Length of frame in packet (in samples)
+ * - bweIndex : Bandwidth estimate in bitstream
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_ReadBwIndex(
+ const WebRtc_Word16* encoded,
+ WebRtc_Word16* bweIndex);
+
+
+
+ /*******************************************************************************
+ * WebRtcIsac_GetNewFrameLen(...)
+ *
+ * returns the frame lenght (in samples) of the next packet. In the case of channel-adaptive
+ * mode, iSAC decides on its frame lenght based on the estimated bottleneck
+ * this allows a user to prepare for the next packet (at the encoder)
+ *
+ * The primary usage is in CE to make the iSAC works in channel-adaptive mode
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Return Value : frame lenght in samples
+ *
+ */
+
+ WebRtc_Word16 WebRtcIsac_GetNewFrameLen(
+ ISACStruct* ISAC_main_inst);
+
+
+ /****************************************************************************
+ * WebRtcIsac_GetRedPayload(...)
+ *
+ * Populates "encoded" with the redundant payload of the recently encoded
+ * frame. This function has to be called once that WebRtcIsac_Encode(...)
+ * returns a positive value. Regardless of the frame-size this function will
+ * be called only once after encoding is completed.
+ *
+ * Input:
+ * - ISAC_main_inst : iSAC struct
+ *
+ * Output:
+ * - encoded : the encoded data vector
+ *
+ *
+ * Return value:
+ * : >0 - Length (in bytes) of coded data
+ * : -1 - Error
+ *
+ *
+ */
+ WebRtc_Word16 WebRtcIsac_GetRedPayload(
+ ISACStruct* ISAC_main_inst,
+ WebRtc_Word16* encoded);
+
+
+ /****************************************************************************
+ * WebRtcIsac_DecodeRcu(...)
+ *
+ * This function decodes a redundant (RCU) iSAC frame. Function is called in
+ * NetEq with a stored RCU payload i case of packet loss. Output speech length
+ * will be a multiple of 480 samples: 480 or 960 samples,
+ * depending on the framesize (30 or 60 ms).
+ *
+ * Input:
+ * - ISAC_main_inst : ISAC instance.
+ * - encoded : encoded ISAC RCU frame(s)
+ * - len : bytes in encoded vector
+ *
+ * Output:
+ * - decoded : The decoded vector
+ *
+ * Return value : >0 - number of samples in decoded vector
+ * -1 - Error
+ */
+ WebRtc_Word16 WebRtcIsac_DecodeRcu(
+ ISACStruct* ISAC_main_inst,
+ const WebRtc_UWord16* encoded,
+ WebRtc_Word16 len,
+ WebRtc_Word16* decoded,
+ WebRtc_Word16* speechType);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_ISAC_H_ */
diff --git a/src/mod/codecs/mod_isac/lattice.c b/src/mod/codecs/mod_isac/lattice.c
new file mode 100644
index 0000000000..a46135a3f7
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lattice.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lattice.c
+ *
+ * contains the normalized lattice filter routines (MA and AR) for iSAC codec
+ *
+ */
+#include "settings.h"
+#include "codec.h"
+
+#include
+#include
+#ifdef WEBRTC_ANDROID
+#include
+#endif
+
+/* filter the signal using normalized lattice filter */
+/* MA filter */
+void WebRtcIsac_NormLatticeFilterMa(int orderCoef,
+ float *stateF,
+ float *stateG,
+ float *lat_in,
+ double *filtcoeflo,
+ double *lat_out)
+{
+ int n,k,i,u,temp1;
+ int ord_1 = orderCoef+1;
+ float sth[MAX_AR_MODEL_ORDER];
+ float cth[MAX_AR_MODEL_ORDER];
+ float inv_cth[MAX_AR_MODEL_ORDER];
+ double a[MAX_AR_MODEL_ORDER+1];
+ float f[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN], g[MAX_AR_MODEL_ORDER+1][HALF_SUBFRAMELEN];
+ float gain1;
+
+ for (u=0;u=0;i--) //get the state of f&g for the first input, for all orders
+ {
+ ARf[i][0] = cth[i]*ARf[i+1][0] - sth[i]*stateG[i];
+ ARg[i+1][0] = sth[i]*ARf[i+1][0] + cth[i]* stateG[i];
+ }
+ ARg[0][0] = ARf[0][0];
+
+ for(n=0;n<(HALF_SUBFRAMELEN-1);n++)
+ {
+ for(k=orderCoef-1;k>=0;k--)
+ {
+ ARf[k][n+1] = cth[k]*ARf[k+1][n+1] - sth[k]*ARg[k][n];
+ ARg[k+1][n+1] = sth[k]*ARf[k+1][n+1] + cth[k]* ARg[k][n];
+ }
+ ARg[0][n+1] = ARf[0][n+1];
+ }
+
+ memcpy(lat_out+u * HALF_SUBFRAMELEN, &(ARf[0][0]), sizeof(float) * HALF_SUBFRAMELEN);
+
+ /* cannot use memcpy in the following */
+ for (i=0;i0; m--)
+ {
+ tmp_inv = 1.0f / cth2;
+ for (k=1; k<=m; k++)
+ {
+ tmp[k] = ((float)a[k] - sth[m] * (float)a[m-k+1]) * tmp_inv;
+ }
+
+ for (k=1; k= 0; i--)
+ {
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm);
+ // Put R in hi and low format
+ R_hi[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ R_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)), 1);
+ }
+
+ // K = A[1] = -R[1] / R[0]
+
+ temp2W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[1],16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[1],1); // R[1] in Q31
+ temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); // abs R[1]
+ temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); // abs(R[1])/R[0] in Q31
+ // Put back the sign on R[1]
+ if (temp2W32 > 0)
+ {
+ temp1W32 = -temp1W32;
+ }
+
+ // Put K in hi and low format
+ K_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ // Store first reflection coefficient
+ K[0] = K_hi;
+
+ temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4); // A[1] in Q27
+
+ // Put A[1] in hi and low format
+ A_hi[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_low[1] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[1], 16)), 1);
+
+ // Alpha = R[0] * (1-K^2)
+
+ temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14) + WEBRTC_SPL_MUL_16_16(K_hi, K_hi))
+ << 1); // temp1W32 = k^2 in Q31
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; // temp1W32 = (1 - K[0]*K[0]) in Q31
+
+ // Store temp1W32 = 1 - K[0]*K[0] on hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Calculate Alpha in Q31
+ temp1W32 = ((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi)
+ + (WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi) >> 15)) << 1);
+
+ // Normalize Alpha and put it in hi and low format
+
+ Alpha_exp = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp);
+ Alpha_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ // Perform the iterative calculations in the Levinson-Durbin algorithm
+
+ for (i = 2; i <= order; i++)
+ {
+ /* ----
+ temp1W32 = R[i] + > R[j]*A[i-j]
+ /
+ ----
+ j=1..i-1
+ */
+
+ temp1W32 = 0;
+
+ for (j = 1; j < i; j++)
+ {
+ // temp1W32 is in Q31
+ temp1W32 += ((WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]) << 1)
+ + (((WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]) >> 15)) << 1));
+ }
+
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4);
+ temp1W32 += (WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_hi[i], 16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)R_low[i], 1));
+
+ // K = -temp1W32 / Alpha
+ temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); // abs(temp1W32)
+ temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); // abs(temp1W32)/Alpha
+
+ // Put the sign of temp1W32 back again
+ if (temp1W32 > 0)
+ {
+ temp3W32 = -temp3W32;
+ }
+
+ // Use the Alpha shifts from earlier to de-normalize
+ norm = WebRtcSpl_NormW32(temp3W32);
+ if ((Alpha_exp <= norm) || (temp3W32 == 0))
+ {
+ temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp);
+ } else
+ {
+ if (temp3W32 > 0)
+ {
+ temp3W32 = (WebRtc_Word32)0x7fffffffL;
+ } else
+ {
+ temp3W32 = (WebRtc_Word32)0x80000000L;
+ }
+ }
+
+ // Put K on hi and low format
+ K_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ K_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)K_hi, 16)), 1);
+
+ // Store Reflection coefficient in Q15
+ K[i - 1] = K_hi;
+
+ // Test for unstable filter.
+ // If unstable return 0 and let the user decide what to do in that case
+
+ if ((WebRtc_Word32)WEBRTC_SPL_ABS_W16(K_hi) > (WebRtc_Word32)32750)
+ {
+ return 0; // Unstable filter
+ }
+
+ /*
+ Compute updated LPC coefficient: Anew[i]
+ Anew[j]= A[j] + K*A[i-j] for j=1..i-1
+ Anew[i]= K
+ */
+
+ for (j = 1; j < i; j++)
+ {
+ // temp1W32 = A[j] in Q27
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[j],16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[j],1);
+
+ // temp1W32 += K*A[i-j] in Q27
+ temp1W32 += ((WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j])
+ + (WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]) >> 15)) << 1);
+
+ // Put Anew in hi and low format
+ A_upd_hi[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ A_upd_low[j] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[j], 16)), 1);
+ }
+
+ // temp3W32 = K in Q27 (Convert from Q31 to Q27)
+ temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4);
+
+ // Store Anew in hi and low format
+ A_upd_hi[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16);
+ A_upd_low[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp3W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_upd_hi[i], 16)), 1);
+
+ // Alpha = Alpha * (1-K^2)
+
+ temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14)
+ + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)) << 1); // K*K in Q31
+
+ temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0
+ temp1W32 = (WebRtc_Word32)0x7fffffffL - temp1W32; // 1 - K*K in Q31
+
+ // Convert 1- K^2 in hi and low format
+ tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
+
+ // Calculate Alpha = Alpha * (1-K^2) in Q31
+ temp1W32 = ((WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi)
+ + (WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low) >> 15)
+ + (WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi) >> 15)) << 1);
+
+ // Normalize Alpha and store it on hi and low format
+
+ norm = WebRtcSpl_NormW32(temp1W32);
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm);
+
+ Alpha_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16);
+ Alpha_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32
+ - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)Alpha_hi, 16)), 1);
+
+ // Update the total normalization of Alpha
+ Alpha_exp = Alpha_exp + norm;
+
+ // Update A[]
+
+ for (j = 1; j <= i; j++)
+ {
+ A_hi[j] = A_upd_hi[j];
+ A_low[j] = A_upd_low[j];
+ }
+ }
+
+ /*
+ Set A[0] to 1.0 and store the A[i] i=1...order in Q12
+ (Convert from Q27 and use rounding)
+ */
+
+ A[0] = 4096;
+
+ for (i = 1; i <= order; i++)
+ {
+ // temp1W32 in Q27
+ temp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_hi[i], 16)
+ + WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)A_low[i], 1);
+ // Round and store upper word
+ A[i] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((temp1W32<<1)+(WebRtc_Word32)32768, 16);
+ }
+ return 1; // Stable filters
+}
diff --git a/src/mod/codecs/mod_isac/lpc_analysis.c b/src/mod/codecs/mod_isac/lpc_analysis.c
new file mode 100644
index 0000000000..854b2d733c
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_analysis.c
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "lpc_analysis.h"
+#include "settings.h"
+#include "codec.h"
+#include "entropy_coding.h"
+
+#include
+#include
+
+#define LEVINSON_EPS 1.0e-10
+
+
+/* window */
+/* Matlab generation code:
+ * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid;
+ * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end
+ */
+static const double kLpcCorrWindow[WINLEN] = {
+ 0.00000000, 0.00000001, 0.00000004, 0.00000010, 0.00000020,
+ 0.00000035, 0.00000055, 0.00000083, 0.00000118, 0.00000163,
+ 0.00000218, 0.00000283, 0.00000361, 0.00000453, 0.00000558, 0.00000679,
+ 0.00000817, 0.00000973, 0.00001147, 0.00001342, 0.00001558,
+ 0.00001796, 0.00002058, 0.00002344, 0.00002657, 0.00002997,
+ 0.00003365, 0.00003762, 0.00004190, 0.00004651, 0.00005144, 0.00005673,
+ 0.00006236, 0.00006837, 0.00007476, 0.00008155, 0.00008875,
+ 0.00009636, 0.00010441, 0.00011290, 0.00012186, 0.00013128,
+ 0.00014119, 0.00015160, 0.00016252, 0.00017396, 0.00018594, 0.00019846,
+ 0.00021155, 0.00022521, 0.00023946, 0.00025432, 0.00026978,
+ 0.00028587, 0.00030260, 0.00031998, 0.00033802, 0.00035674,
+ 0.00037615, 0.00039626, 0.00041708, 0.00043863, 0.00046092, 0.00048396,
+ 0.00050775, 0.00053233, 0.00055768, 0.00058384, 0.00061080,
+ 0.00063858, 0.00066720, 0.00069665, 0.00072696, 0.00075813,
+ 0.00079017, 0.00082310, 0.00085692, 0.00089164, 0.00092728, 0.00096384,
+ 0.00100133, 0.00103976, 0.00107914, 0.00111947, 0.00116077,
+ 0.00120304, 0.00124630, 0.00129053, 0.00133577, 0.00138200,
+ 0.00142924, 0.00147749, 0.00152676, 0.00157705, 0.00162836, 0.00168070,
+ 0.00173408, 0.00178850, 0.00184395, 0.00190045, 0.00195799,
+ 0.00201658, 0.00207621, 0.00213688, 0.00219860, 0.00226137,
+ 0.00232518, 0.00239003, 0.00245591, 0.00252284, 0.00259079, 0.00265977,
+ 0.00272977, 0.00280078, 0.00287280, 0.00294582, 0.00301984,
+ 0.00309484, 0.00317081, 0.00324774, 0.00332563, 0.00340446,
+ 0.00348421, 0.00356488, 0.00364644, 0.00372889, 0.00381220, 0.00389636,
+ 0.00398135, 0.00406715, 0.00415374, 0.00424109, 0.00432920,
+ 0.00441802, 0.00450754, 0.00459773, 0.00468857, 0.00478001,
+ 0.00487205, 0.00496464, 0.00505775, 0.00515136, 0.00524542, 0.00533990,
+ 0.00543476, 0.00552997, 0.00562548, 0.00572125, 0.00581725,
+ 0.00591342, 0.00600973, 0.00610612, 0.00620254, 0.00629895,
+ 0.00639530, 0.00649153, 0.00658758, 0.00668341, 0.00677894, 0.00687413,
+ 0.00696891, 0.00706322, 0.00715699, 0.00725016, 0.00734266,
+ 0.00743441, 0.00752535, 0.00761540, 0.00770449, 0.00779254,
+ 0.00787947, 0.00796519, 0.00804963, 0.00813270, 0.00821431, 0.00829437,
+ 0.00837280, 0.00844949, 0.00852436, 0.00859730, 0.00866822,
+ 0.00873701, 0.00880358, 0.00886781, 0.00892960, 0.00898884,
+ 0.00904542, 0.00909923, 0.00915014, 0.00919805, 0.00924283, 0.00928436,
+ 0.00932252, 0.00935718, 0.00938821, 0.00941550, 0.00943890,
+ 0.00945828, 0.00947351, 0.00948446, 0.00949098, 0.00949294,
+ 0.00949020, 0.00948262, 0.00947005, 0.00945235, 0.00942938, 0.00940099,
+ 0.00936704, 0.00932738, 0.00928186, 0.00923034, 0.00917268,
+ 0.00910872, 0.00903832, 0.00896134, 0.00887763, 0.00878706,
+ 0.00868949, 0.00858478, 0.00847280, 0.00835343, 0.00822653, 0.00809199,
+ 0.00794970, 0.00779956, 0.00764145, 0.00747530, 0.00730103,
+ 0.00711857, 0.00692787, 0.00672888, 0.00652158, 0.00630597,
+ 0.00608208, 0.00584994, 0.00560962, 0.00536124, 0.00510493, 0.00484089,
+ 0.00456935, 0.00429062, 0.00400505, 0.00371310, 0.00341532,
+ 0.00311238, 0.00280511, 0.00249452, 0.00218184, 0.00186864,
+ 0.00155690, 0.00124918, 0.00094895, 0.00066112, 0.00039320, 0.00015881
+};
+
+double WebRtcIsac_LevDurb(double *a, double *k, double *r, int order)
+{
+
+ double sum, alpha;
+ int m, m_h, i;
+ alpha = 0; //warning -DH
+ a[0] = 1.0;
+ if (r[0] < LEVINSON_EPS) { /* if r[0] <= 0, set LPC coeff. to zero */
+ for (i = 0; i < order; i++) {
+ k[i] = 0;
+ a[i+1] = 0;
+ }
+ } else {
+ a[1] = k[0] = -r[1]/r[0];
+ alpha = r[0] + r[1] * k[0];
+ for (m = 1; m < order; m++){
+ sum = r[m + 1];
+ for (i = 0; i < m; i++){
+ sum += a[i+1] * r[m - i];
+ }
+ k[m] = -sum / alpha;
+ alpha += k[m] * sum;
+ m_h = (m + 1) >> 1;
+ for (i = 0; i < m_h; i++){
+ sum = a[i+1] + k[m] * a[m - i];
+ a[m - i] += k[m] * a[i+1];
+ a[i+1] = sum;
+ }
+ a[m+1] = k[m];
+ }
+ }
+ return alpha;
+}
+
+
+//was static before, but didn't work with MEX file
+void WebRtcIsac_GetVars(const double *input, const WebRtc_Word16 *pitchGains_Q12,
+ double *oldEnergy, double *varscale)
+{
+ double nrg[4], chng, pg;
+ int k;
+
+ double pitchGains[4]={0,0,0,0};;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES_QUARTER + QLOOKAHEAD) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF + QLOOKAHEAD) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4 + QLOOKAHEAD) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* Find average pitch gain */
+ pg = 0.0;
+ for (k=0; k<4; k++)
+ {
+ pitchGains[k] = ((float)pitchGains_Q12[k])/4096;
+ pg += pitchGains[k];
+ }
+ pg *= 0.25;
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = 0.0 + 1.0 * exp( -1.4 * exp(-200.0 * pg*pg*pg) / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+void
+WebRtcIsac_GetVarsUB(
+ const double* input,
+ double* oldEnergy,
+ double* varscale)
+{
+ double nrg[4], chng;
+ int k;
+
+ /* Calculate energies of first and second frame halfs */
+ nrg[0] = 0.0001;
+ for (k = 0; k < (FRAMESAMPLES_QUARTER) / 2; k++) {
+ nrg[0] += input[k]*input[k];
+ }
+ nrg[1] = 0.0001;
+ for ( ; k < (FRAMESAMPLES_HALF) / 2; k++) {
+ nrg[1] += input[k]*input[k];
+ }
+ nrg[2] = 0.0001;
+ for ( ; k < (FRAMESAMPLES*3/4) / 2; k++) {
+ nrg[2] += input[k]*input[k];
+ }
+ nrg[3] = 0.0001;
+ for ( ; k < (FRAMESAMPLES) / 2; k++) {
+ nrg[3] += input[k]*input[k];
+ }
+
+ /* Calculate average level change */
+ chng = 0.25 * (fabs(10.0 * log10(nrg[3] / nrg[2])) +
+ fabs(10.0 * log10(nrg[2] / nrg[1])) +
+ fabs(10.0 * log10(nrg[1] / nrg[0])) +
+ fabs(10.0 * log10(nrg[0] / *oldEnergy)));
+
+
+ /* If pitch gain is low and energy constant - increase noise level*/
+ /* Matlab code:
+ pg = 0:.01:.45; plot(pg, 0.0 + 1.0 * exp( -1.0 * exp(-200.0 * pg.*pg.*pg) / (1.0 + 0.4 * 0) ))
+ */
+ *varscale = exp( -1.4 / (1.0 + 0.4 * chng) );
+
+ *oldEnergy = nrg[3];
+}
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+ double signal_noise_ratio, const WebRtc_Word16 *pitchGains_Q12,
+ double *lo_coeff, double *hi_coeff)
+{
+ int k, n, j, pos1, pos2;
+ double varscale;
+
+ double DataLo[WINLEN], DataHi[WINLEN];
+ double corrlo[ORDERLO+2], corrlo2[ORDERLO+1];
+ double corrhi[ORDERHI+1];
+ double k_veclo[ORDERLO], k_vechi[ORDERHI];
+
+ double a_LO[ORDERLO+1], a_HI[ORDERHI+1];
+ double tmp, res_nrg;
+
+ double FwdA, FwdB;
+
+ /* hearing threshold level in dB; higher value gives more noise */
+ const double HearThresOffset = -28.0;
+
+ /* bandwdith expansion factors for low- and high band */
+ const double gammaLo = 0.9;
+ const double gammaHi = 0.8;
+
+ /* less-noise-at-low-frequencies factor */
+ double aa;
+
+
+ /* convert from dB to signal level */
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46; /* divide by sqrt(12) */
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVars(inLo, pitchGains_Q12, &(maskdata->OldEnergy), &varscale);
+
+ /* less-noise-at-low-frequencies factor */
+ aa = 0.35 * (0.5 + 0.5 * varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++)
+ maskdata->DataBufferLo[pos1 + WINLEN - QLOOKAHEAD] = inLo[pos1];
+
+ for (k = 0; k < SUBFRAMES; k++) {
+
+ /* Update input buffer and multiply signal with window */
+ for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 + UPDATE/2];
+ maskdata->DataBufferHi[pos1] = maskdata->DataBufferHi[pos1 + UPDATE/2];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = k * UPDATE/2;
+ for (n = 0; n < UPDATE/2; n++, pos1++) {
+ maskdata->DataBufferLo[pos1] = inLo[QLOOKAHEAD + pos2];
+ maskdata->DataBufferHi[pos1] = inHi[pos2++];
+ DataLo[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ DataHi[pos1] = maskdata->DataBufferHi[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ WebRtcIsac_AutoCorr(corrlo, DataLo, WINLEN, ORDERLO+1); /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrhi, DataHi, WINLEN, ORDERHI);
+
+
+ /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */
+ corrlo2[0] = (1.0+aa*aa) * corrlo[0] - 2.0*aa * corrlo[1];
+ tmp = (1.0 + aa*aa);
+ for (n = 1; n <= ORDERLO; n++) {
+ corrlo2[n] = tmp * corrlo[n] - aa * (corrlo[n-1] + corrlo[n+1]);
+ }
+ tmp = (1.0+aa) * (1.0+aa);
+ for (n = 0; n <= ORDERHI; n++) {
+ corrhi[n] = tmp * corrhi[n];
+ }
+
+ /* add white noise floor */
+ corrlo2[0] += 1e-6;
+ corrhi[0] += 1e-6;
+
+
+ FwdA = 0.01;
+ FwdB = 0.01;
+
+ /* recursive filtering of correlation over subframes */
+ for (n = 0; n <= ORDERLO; n++) {
+ maskdata->CorrBufLo[n] = FwdA * maskdata->CorrBufLo[n] + corrlo2[n];
+ corrlo2[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufLo[n] + (1.0-FwdB) * corrlo2[n];
+ }
+ for (n = 0; n <= ORDERHI; n++) {
+ maskdata->CorrBufHi[n] = FwdA * maskdata->CorrBufHi[n] + corrhi[n];
+ corrhi[n] = ((1.0-FwdA)*FwdB) * maskdata->CorrBufHi[n] + (1.0-FwdB) * corrhi[n];
+ }
+
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(a_LO, k_veclo, corrlo2, ORDERLO);
+ WebRtcIsac_LevDurb(a_HI, k_vechi, corrhi, ORDERHI);
+
+ /* bandwidth expansion */
+ tmp = gammaLo;
+ for (n = 1; n <= ORDERLO; n++) {
+ a_LO[n] *= tmp;
+ tmp *= gammaLo;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERLO; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_LO[j] * corrlo2[j-n] * a_LO[n];
+ }
+ for (n = j+1; n <= ORDERLO; n++) {
+ res_nrg += a_LO[j] * corrlo2[n-j] * a_LO[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ *lo_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERLO; n++) {
+ *lo_coeff++ = a_LO[n];
+ }
+
+
+ /* bandwidth expansion */
+ tmp = gammaHi;
+ for (n = 1; n <= ORDERHI; n++) {
+ a_HI[n] *= tmp;
+ tmp *= gammaHi;
+ }
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for (j = 0; j <= ORDERHI; j++) {
+ for (n = 0; n <= j; n++) {
+ res_nrg += a_HI[j] * corrhi[j-n] * a_HI[n];
+ }
+ for (n = j+1; n <= ORDERHI; n++) {
+ res_nrg += a_HI[j] * corrhi[n-j] * a_HI[n];
+ }
+ }
+
+ /* add hearing threshold and compute of the gain */
+ *hi_coeff++ = S_N_R / (sqrt(res_nrg) / varscale + H_T_H);
+
+ /* copy coefficients to output array */
+ for (n = 1; n <= ORDERHI; n++) {
+ *hi_coeff++ = a_HI[n];
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcCoefUb()
+ *
+ * Compute LP coefficients and correlation coefficients. At 12 kHz LP
+ * coefficients of the first and the last sub-frame is computed. At 16 kHz
+ * LP coefficients of 4th, 8th and 12th sub-frames are computed. We always
+ * compute correlation coefficients of all sub-frames.
+ *
+ * Inputs:
+ * -inSignal : Input signal
+ * -maskdata : a structure keeping signal from previous frame.
+ * -bandwidth : specifies if the codec is in 0-16 kHz mode or
+ * 0-12 kHz mode.
+ *
+ * Outputs:
+ * -lpCoeff : pointer to a buffer where A-polynomials are
+ * written to (first coeff is 1 and it is not
+ * written)
+ * -corrMat : a matrix where correlation coefficients of each
+ * sub-frame are written to one row.
+ * -varscale : a scale used to compute LPC gains.
+ */
+void
+WebRtcIsac_GetLpcCoefUb(
+ double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corrMat[][UB_LPC_ORDER + 1],
+ double* varscale,
+ WebRtc_Word16 bandwidth)
+{
+ int frameCntr, activeFrameCntr, n, pos1, pos2;
+ WebRtc_Word16 criterion1;
+ WebRtc_Word16 criterion2;
+ WebRtc_Word16 numSubFrames = SUBFRAMES * (1 + (bandwidth == isac16kHz));
+ double data[WINLEN];
+ double corrSubFrame[UB_LPC_ORDER+2];
+ double reflecCoeff[UB_LPC_ORDER];
+
+ double aPolynom[UB_LPC_ORDER+1];
+ double tmp;
+
+ /* bandwdith expansion factors */
+ const double gamma = 0.9;
+
+ /* change quallevel depending on pitch gains and level fluctuations */
+ WebRtcIsac_GetVarsUB(inSignal, &(maskdata->OldEnergy), varscale);
+
+ /* replace data in buffer by new look-ahead data */
+ for(frameCntr = 0, activeFrameCntr = 0; frameCntr < numSubFrames;
+ frameCntr++)
+ {
+ if(frameCntr == SUBFRAMES)
+ {
+ // we are in 16 kHz
+ varscale++;
+ WebRtcIsac_GetVarsUB(&inSignal[FRAMESAMPLES_HALF],
+ &(maskdata->OldEnergy), varscale);
+ }
+ /* Update input buffer and multiply signal with window */
+ for(pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++)
+ {
+ maskdata->DataBufferLo[pos1] = maskdata->DataBufferLo[pos1 +
+ UPDATE/2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+ pos2 = frameCntr * UPDATE/2;
+ for(n = 0; n < UPDATE/2; n++, pos1++, pos2++)
+ {
+ maskdata->DataBufferLo[pos1] = inSignal[pos2];
+ data[pos1] = maskdata->DataBufferLo[pos1] * kLpcCorrWindow[pos1];
+ }
+
+ /* Get correlation coefficients */
+ /* computing autocorrelation */
+ WebRtcIsac_AutoCorr(corrSubFrame, data, WINLEN, UB_LPC_ORDER+1);
+ memcpy(corrMat[frameCntr], corrSubFrame,
+ (UB_LPC_ORDER+1)*sizeof(double));
+
+ criterion1 = ((frameCntr == 0) || (frameCntr == (SUBFRAMES - 1))) &&
+ (bandwidth == isac12kHz);
+ criterion2 = (((frameCntr+1) % 4) == 0) &&
+ (bandwidth == isac16kHz);
+ if(criterion1 || criterion2)
+ {
+ /* add noise */
+ corrSubFrame[0] += 1e-6;
+ /* compute prediction coefficients */
+ WebRtcIsac_LevDurb(aPolynom, reflecCoeff, corrSubFrame,
+ UB_LPC_ORDER);
+
+ /* bandwidth expansion */
+ tmp = gamma;
+ for (n = 1; n <= UB_LPC_ORDER; n++)
+ {
+ *lpCoeff++ = aPolynom[n] * tmp;
+ tmp *= gamma;
+ }
+ activeFrameCntr++;
+ }
+ }
+}
+
+
+
+/******************************************************************************
+ * WebRtcIsac_GetLpcGain()
+ *
+ * Compute the LPC gains for each sub-frame, given the LPC of each sub-frame
+ * and the corresponding correlation coefficients.
+ *
+ * Inputs:
+ * -signal_noise_ratio : the desired SNR in dB.
+ * -numVecs : number of sub-frames
+ * -corrMat : a matrix of correlation coefficients where
+ * each row is a set of correlation coefficients of
+ * one sub-frame.
+ * -varscale : a scale computed when WebRtcIsac_GetLpcCoefUb()
+ * is called.
+ *
+ * Outputs:
+ * -gain : pointer to a buffer where LP gains are written.
+ *
+ */
+void
+WebRtcIsac_GetLpcGain(
+ double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrMat[][UB_LPC_ORDER + 1],
+ const double* varscale)
+{
+ WebRtc_Word16 j, n;
+ WebRtc_Word16 subFrameCntr;
+ double aPolynom[ORDERLO + 1];
+ double res_nrg;
+
+ const double HearThresOffset = -28.0;
+ const double H_T_H = pow(10.0, 0.05 * HearThresOffset);
+ /* divide by sqrt(12) = 3.46 */
+ const double S_N_R = pow(10.0, 0.05 * signal_noise_ratio) / 3.46;
+
+ aPolynom[0] = 1;
+ for(subFrameCntr = 0; subFrameCntr < numVecs; subFrameCntr++)
+ {
+ if(subFrameCntr == SUBFRAMES)
+ {
+ // we are in second half of a SWB frame. use new varscale
+ varscale++;
+ }
+ memcpy(&aPolynom[1], &filtCoeffVecs[(subFrameCntr * (UB_LPC_ORDER + 1)) +
+ 1], sizeof(double) * UB_LPC_ORDER);
+
+ /* residual energy */
+ res_nrg = 0.0;
+ for(j = 0; j <= UB_LPC_ORDER; j++)
+ {
+ for(n = 0; n <= j; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][j-n] *
+ aPolynom[n];
+ }
+ for(n = j+1; n <= UB_LPC_ORDER; n++)
+ {
+ res_nrg += aPolynom[j] * corrMat[subFrameCntr][n-j] *
+ aPolynom[n];
+ }
+ }
+
+ /* add hearing threshold and compute the gain */
+ gain[subFrameCntr] = S_N_R / (sqrt(res_nrg) / *varscale + H_T_H);
+ }
+}
diff --git a/src/mod/codecs/mod_isac/lpc_analysis.h b/src/mod/codecs/mod_isac/lpc_analysis.h
new file mode 100644
index 0000000000..4eafeac7bc
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_analysis.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_analysis.h
+ *
+ * LPC functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYSIS_H_
+
+#include "settings.h"
+#include "structs.h"
+
+double WebRtcIsac_LevDurb(double *a, double *k, double *r, int order);
+
+void WebRtcIsac_GetVars(const double *input, const WebRtc_Word16 *pitchGains_Q12,
+ double *oldEnergy, double *varscale);
+
+void WebRtcIsac_GetLpcCoefLb(double *inLo, double *inHi, MaskFiltstr *maskdata,
+ double signal_noise_ratio, const WebRtc_Word16 *pitchGains_Q12,
+ double *lo_coeff, double *hi_coeff);
+
+
+void WebRtcIsac_GetLpcGain(
+ double signal_noise_ratio,
+ const double* filtCoeffVecs,
+ int numVecs,
+ double* gain,
+ double corrLo[][UB_LPC_ORDER + 1],
+ const double* varscale);
+
+void WebRtcIsac_GetLpcCoefUb(
+ double* inSignal,
+ MaskFiltstr* maskdata,
+ double* lpCoeff,
+ double corr[][UB_LPC_ORDER + 1],
+ double* varscale,
+ WebRtc_Word16 bandwidth);
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_ANALYIS_H_ */
diff --git a/src/mod/codecs/mod_isac/lpc_gain_swb_tables.c b/src/mod/codecs/mod_isac/lpc_gain_swb_tables.c
new file mode 100644
index 0000000000..25c69cbfef
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_gain_swb_tables.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.c
+ *
+ * This file defines tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#include "lpc_gain_swb_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+const double WebRtcIsac_kQSizeLpcGain = 0.100000;
+
+const double WebRtcIsac_kMeanLpcGain = -3.3822;
+
+/*
+* The smallest reconstruction points for quantiztion of
+* LPC gains.
+*/
+const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES] =
+{
+ -0.800000, -1.000000, -1.200000, -2.200000, -3.000000, -12.700000
+};
+
+/*
+* Number of reconstruction points of quantizers for LPC Gains.
+*/
+const WebRtc_Word16 WebRtcIsac_kNumQCellLpcGain[SUBFRAMES] =
+{
+ 17, 20, 25, 45, 77, 170
+};
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES] =
+{
+ 8, 10, 12, 22, 38, 85
+};
+
+/*
+* The following 6 vectors define CDF of 6 decorrelated LPC
+* gains.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec0[18] =
+{
+ 0, 10, 27, 83, 234, 568, 1601, 4683, 16830, 57534, 63437,
+ 64767, 65229, 65408, 65483, 65514, 65527, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec1[21] =
+{
+ 0, 15, 33, 84, 185, 385, 807, 1619, 3529, 7850, 19488,
+ 51365, 62437, 64548, 65088, 65304, 65409, 65484, 65507, 65522, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec2[26] =
+{
+ 0, 15, 29, 54, 89, 145, 228, 380, 652, 1493, 4260,
+ 12359, 34133, 50749, 57224, 60814, 62927, 64078, 64742, 65103, 65311, 65418,
+ 65473, 65509, 65521, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec3[46] =
+{
+ 0, 8, 12, 16, 26, 42, 56, 76, 111, 164, 247,
+ 366, 508, 693, 1000, 1442, 2155, 3188, 4854, 7387, 11249, 17617,
+ 30079, 46711, 56291, 60127, 62140, 63258, 63954, 64384, 64690, 64891, 65031,
+ 65139, 65227, 65293, 65351, 65399, 65438, 65467, 65492, 65504, 65510, 65518,
+ 65523, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec4[78] =
+{
+ 0, 17, 29, 39, 51, 70, 104, 154, 234, 324, 443,
+ 590, 760, 971, 1202, 1494, 1845, 2274, 2797, 3366, 4088, 4905,
+ 5899, 7142, 8683, 10625, 12983, 16095, 20637, 28216, 38859, 47237, 51537,
+ 54150, 56066, 57583, 58756, 59685, 60458, 61103, 61659, 62144, 62550, 62886,
+ 63186, 63480, 63743, 63954, 64148, 64320, 64467, 64600, 64719, 64837, 64939,
+ 65014, 65098, 65160, 65211, 65250, 65290, 65325, 65344, 65366, 65391, 65410,
+ 65430, 65447, 65460, 65474, 65487, 65494, 65501, 65509, 65513, 65518, 65520,
+ 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec5[171] =
+{
+ 0, 10, 12, 14, 16, 18, 23, 29, 35, 42, 51,
+ 58, 65, 72, 78, 87, 96, 103, 111, 122, 134, 150,
+ 167, 184, 202, 223, 244, 265, 289, 315, 346, 379, 414,
+ 450, 491, 532, 572, 613, 656, 700, 751, 802, 853, 905,
+ 957, 1021, 1098, 1174, 1250, 1331, 1413, 1490, 1565, 1647, 1730,
+ 1821, 1913, 2004, 2100, 2207, 2314, 2420, 2532, 2652, 2783, 2921,
+ 3056, 3189, 3327, 3468, 3640, 3817, 3993, 4171, 4362, 4554, 4751,
+ 4948, 5142, 5346, 5566, 5799, 6044, 6301, 6565, 6852, 7150, 7470,
+ 7797, 8143, 8492, 8835, 9181, 9547, 9919, 10315, 10718, 11136, 11566,
+ 12015, 12482, 12967, 13458, 13953, 14432, 14903, 15416, 15936, 16452, 16967,
+ 17492, 18024, 18600, 19173, 19736, 20311, 20911, 21490, 22041, 22597, 23157,
+ 23768, 24405, 25034, 25660, 26280, 26899, 27614, 28331, 29015, 29702, 30403,
+ 31107, 31817, 32566, 33381, 34224, 35099, 36112, 37222, 38375, 39549, 40801,
+ 42074, 43350, 44626, 45982, 47354, 48860, 50361, 51845, 53312, 54739, 56026,
+ 57116, 58104, 58996, 59842, 60658, 61488, 62324, 63057, 63769, 64285, 64779,
+ 65076, 65344, 65430, 65500, 65517, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LPC Gains
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES] =
+{
+ WebRtcIsac_kLpcGainCdfVec0, WebRtcIsac_kLpcGainCdfVec1,
+ WebRtcIsac_kLpcGainCdfVec2, WebRtcIsac_kLpcGainCdfVec3,
+ WebRtcIsac_kLpcGainCdfVec4, WebRtcIsac_kLpcGainCdfVec5
+};
+
+/*
+* A matrix to decorrellate LPC gains of subframes.
+*/
+const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES] =
+{
+ {-0.150860, 0.327872, 0.367220, 0.504613, 0.559270, 0.409234},
+ { 0.457128, -0.613591, -0.289283, -0.029734, 0.393760, 0.418240},
+ {-0.626043, 0.136489, -0.439118, -0.448323, 0.135987, 0.420869},
+ { 0.526617, 0.480187, 0.242552, -0.488754, -0.158713, 0.411331},
+ {-0.302587, -0.494953, 0.588112, -0.063035, -0.404290, 0.387510},
+ { 0.086378, 0.147714, -0.428875, 0.548300, -0.570121, 0.401391}
+};
diff --git a/src/mod/codecs/mod_isac/lpc_gain_swb_tables.h b/src/mod/codecs/mod_isac/lpc_gain_swb_tables.h
new file mode 100644
index 0000000000..1eba97c8ba
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_gain_swb_tables.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables_LPCGain.h
+ *
+ * This file declares tables used for entropy coding of LPC Gain
+ * of upper-band.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+extern const double WebRtcIsac_kQSizeLpcGain;
+
+extern const double WebRtcIsac_kLeftRecPointLpcGain[SUBFRAMES];
+
+extern const WebRtc_Word16 WebRtcIsac_kNumQCellLpcGain[SUBFRAMES];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainEntropySearch[SUBFRAMES];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec0[18];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec1[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec2[26];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec3[46];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec4[78];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcGainCdfVec5[171];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcGainCdfMat[SUBFRAMES];
+
+extern const double WebRtcIsac_kLpcGainDecorrMat[SUBFRAMES][SUBFRAMES];
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
diff --git a/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.c b/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.c
new file mode 100644
index 0000000000..695d583277
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#include "lpc_shape_swb12_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER] =
+{
+ 0.03748928306641, 0.09453441192543, -0.01112522344398, 0.03800237516842
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.00075365493856, -0.05809964887743, -0.23397966154116, 0.97050367376411},
+ { 0.00625021257734, -0.17299965610679, 0.95977735920651, 0.22104179375008},
+ { 0.20543384258374, -0.96202143495696, -0.15301870801552, -0.09432375099565},
+ {-0.97865075648479, -0.20300322280841, -0.02581111653779, -0.01913568980258}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME] =
+{
+ { 0.70650597970460, -0.70770707262373},
+ {-0.70770707262373, -0.70650597970460}
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb12 = 0.150000;
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME] =
+{
+ -0.900000, -1.050000, -1.350000, -1.800000, -1.350000, -1.650000,
+ -2.250000, -3.450000
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 19, 27, 19, 24, 32, 48
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 9, 13, 9, 12, 16, 24
+};
+
+/*
+* The following 8 vectors define CDF of 8 decorrelated LAR
+* coefficients.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec0Ub12[14] =
+{
+ 0, 13, 95, 418, 1687, 6498, 21317, 44200, 59029, 63849, 65147,
+ 65449, 65525, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub12[16] =
+{
+ 0, 10, 59, 255, 858, 2667, 8200, 22609, 42988, 57202, 62947,
+ 64743, 65308, 65476, 65522, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub12[20] =
+{
+ 0, 18, 40, 118, 332, 857, 2017, 4822, 11321, 24330, 41279,
+ 54342, 60637, 63394, 64659, 65184, 65398, 65482, 65518, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub12[28] =
+{
+ 0, 21, 38, 90, 196, 398, 770, 1400, 2589, 4650, 8211,
+ 14933, 26044, 39592, 50814, 57452, 60971, 62884, 63995, 64621, 65019, 65273,
+ 65410, 65480, 65514, 65522, 65531, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub12[20] =
+{
+ 0, 7, 46, 141, 403, 969, 2132, 4649, 10633, 24902, 43254,
+ 54665, 59928, 62674, 64173, 64938, 65293, 65464, 65523, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub12[25] =
+{
+ 0, 7, 22, 72, 174, 411, 854, 1737, 3545, 6774, 13165,
+ 25221, 40980, 52821, 58714, 61706, 63472, 64437, 64989, 65287, 65430, 65503,
+ 65525, 65529, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub12[33] =
+{
+ 0, 11, 21, 36, 65, 128, 228, 401, 707, 1241, 2126,
+ 3589, 6060, 10517, 18853, 31114, 42477, 49770, 54271, 57467, 59838, 61569,
+ 62831, 63772, 64433, 64833, 65123, 65306, 65419, 65466, 65499, 65519, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub12[49] =
+{
+ 0, 14, 34, 67, 107, 167, 245, 326, 449, 645, 861,
+ 1155, 1508, 2003, 2669, 3544, 4592, 5961, 7583, 9887, 13256, 18765,
+ 26519, 34077, 40034, 44349, 47795, 50663, 53262, 55473, 57458, 59122, 60592,
+ 61742, 62690, 63391, 63997, 64463, 64794, 65045, 65207, 65309, 65394, 65443,
+ 65478, 65504, 65514, 65523, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME] =
+{
+ WebRtcIsac_kLpcShapeCdfVec0Ub12, WebRtcIsac_kLpcShapeCdfVec1Ub12,
+ WebRtcIsac_kLpcShapeCdfVec2Ub12, WebRtcIsac_kLpcShapeCdfVec3Ub12,
+ WebRtcIsac_kLpcShapeCdfVec4Ub12, WebRtcIsac_kLpcShapeCdfVec5Ub12,
+ WebRtcIsac_kLpcShapeCdfVec6Ub12, WebRtcIsac_kLpcShapeCdfVec7Ub12
+};
diff --git a/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.h b/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.h
new file mode 100644
index 0000000000..1e93847fae
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_shape_swb12_tables.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb12_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 12 kHz.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+extern const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kMeanLpcGain;
+
+extern const double WebRtcIsac_kIntraVecDecorrMatUb12[UB_LPC_ORDER][UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb12
+[UB_LPC_VEC_PER_FRAME][UB_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb12;
+
+extern const double WebRtcIsac_kLpcShapeLeftRecPointUb12
+[UB_LPC_ORDER*UB_LPC_VEC_PER_FRAME];
+
+
+extern const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec0Ub12[14];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub12[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub12[20];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub12[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub12[20];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub12[25];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub12[33];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub12[49];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb12
+[UB_LPC_ORDER * UB_LPC_VEC_PER_FRAME];
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
diff --git a/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.c b/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.c
new file mode 100644
index 0000000000..89f45233f5
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * SWB16_KLT_Tables.c
+ *
+ * This file defines tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#include "lpc_shape_swb16_tables.h"
+#include "settings.h"
+#include "typedefs.h"
+
+/*
+* Mean value of LAR
+*/
+const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER] =
+{
+0.454978, 0.364747, 0.102999, 0.104523
+};
+
+/*
+* A rotation matrix to decorrelate intra-vector correlation,
+* i.e. correlation among components of LAR vector.
+*/
+const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER] =
+{
+ {-0.020528, -0.085858, -0.002431, 0.996093},
+ {-0.033155, 0.036102, 0.998786, 0.004866},
+ { 0.202627, 0.974853, -0.028940, 0.088132},
+ {-0.978479, 0.202454, -0.039785, -0.002811}
+};
+
+/*
+* A rotation matrix to remove correlation among LAR coefficients
+* of different LAR vectors. One might guess that decorrelation matrix
+* for the first component should differ from the second component
+* but we haven't observed a significant benefit of having different
+* decorrelation matrices for different components.
+*/
+const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME] =
+{
+ { 0.291675, -0.515786, 0.644927, 0.482658},
+ {-0.647220, 0.479712, 0.289556, 0.516856},
+ { 0.643084, 0.485489, -0.289307, 0.516763},
+ {-0.287185, -0.517823, -0.645389, 0.482553}
+};
+
+/*
+* The following 16 vectors define CDF of 16 decorrelated LAR
+* coefficients.
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub16[14] =
+{
+ 0, 2, 20, 159, 1034, 5688, 20892, 44653,
+ 59849, 64485, 65383, 65518, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub16[16] =
+{
+ 0, 1, 7, 43, 276, 1496, 6681, 21653,
+ 43891, 58859, 64022, 65248, 65489, 65529, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub16[18] =
+{
+ 0, 1, 9, 54, 238, 933, 3192, 9461,
+ 23226, 42146, 56138, 62413, 64623, 65300, 65473, 65521,
+ 65533, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub16[30] =
+{
+ 0, 2, 4, 8, 17, 36, 75, 155,
+ 329, 683, 1376, 2662, 5047, 9508, 17526, 29027,
+ 40363, 48997, 55096, 59180, 61789, 63407, 64400, 64967,
+ 65273, 65429, 65497, 65526, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub16[16] =
+{
+ 0, 1, 10, 63, 361, 1785, 7407, 22242,
+ 43337, 58125, 63729, 65181, 65472, 65527, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub16[17] =
+{
+ 0, 1, 7, 29, 134, 599, 2443, 8590,
+ 22962, 42635, 56911, 63060, 64940, 65408, 65513, 65531,
+ 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub16[21] =
+{
+ 0, 1, 5, 16, 57, 191, 611, 1808,
+ 4847, 11755, 24612, 40910, 53789, 60698, 63729, 64924,
+ 65346, 65486, 65523, 65532, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub16[36] =
+{
+ 0, 1, 4, 12, 25, 55, 104, 184,
+ 314, 539, 926, 1550, 2479, 3861, 5892, 8845,
+ 13281, 20018, 29019, 38029, 45581, 51557, 56057, 59284,
+ 61517, 63047, 64030, 64648, 65031, 65261, 65402, 65480,
+ 65518, 65530, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec8Ub16[21] =
+{
+ 0, 1, 2, 7, 26, 103, 351, 1149,
+ 3583, 10204, 23846, 41711, 55361, 61917, 64382, 65186,
+ 65433, 65506, 65528, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub160[21] =
+{
+ 0, 6, 19, 63, 205, 638, 1799, 4784,
+ 11721, 24494, 40803, 53805, 60886, 63822, 64931, 65333,
+ 65472, 65517, 65530, 65533, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub161[28] =
+{
+ 0, 1, 3, 11, 31, 86, 221, 506,
+ 1101, 2296, 4486, 8477, 15356, 26079, 38941, 49952,
+ 57165, 61257, 63426, 64549, 65097, 65351, 65463, 65510,
+ 65526, 65532, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub162[55] =
+{
+ 0, 3, 12, 23, 42, 65, 89, 115,
+ 150, 195, 248, 327, 430, 580, 784, 1099,
+ 1586, 2358, 3651, 5899, 9568, 14312, 19158, 23776,
+ 28267, 32663, 36991, 41153, 45098, 48680, 51870, 54729,
+ 57141, 59158, 60772, 62029, 63000, 63761, 64322, 64728,
+ 65000, 65192, 65321, 65411, 65463, 65496, 65514, 65523,
+ 65527, 65529, 65531, 65532, 65533, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub163[26] =
+{
+ 0, 2, 4, 10, 21, 48, 114, 280,
+ 701, 1765, 4555, 11270, 24267, 41213, 54285, 61003,
+ 63767, 64840, 65254, 65421, 65489, 65514, 65526, 65532,
+ 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub164[28] =
+{
+ 0, 1, 3, 6, 15, 36, 82, 196,
+ 453, 1087, 2557, 5923, 13016, 25366, 40449, 52582,
+ 59539, 62896, 64389, 65033, 65316, 65442, 65494, 65519,
+ 65529, 65533, 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub165[34] =
+{
+ 0, 2, 4, 8, 18, 35, 73, 146,
+ 279, 524, 980, 1789, 3235, 5784, 10040, 16998,
+ 27070, 38543, 48499, 55421, 59712, 62257, 63748, 64591,
+ 65041, 65278, 65410, 65474, 65508, 65522, 65530, 65533,
+ 65534, 65535
+};
+
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub166[71] =
+{
+ 0, 1, 2, 6, 13, 26, 55, 92,
+ 141, 191, 242, 296, 355, 429, 522, 636,
+ 777, 947, 1162, 1428, 1753, 2137, 2605, 3140,
+ 3743, 4409, 5164, 6016, 6982, 8118, 9451, 10993,
+ 12754, 14810, 17130, 19780, 22864, 26424, 30547, 35222,
+ 40140, 44716, 48698, 52056, 54850, 57162, 59068, 60643,
+ 61877, 62827, 63561, 64113, 64519, 64807, 65019, 65167,
+ 65272, 65343, 65399, 65440, 65471, 65487, 65500, 65509,
+ 65518, 65524, 65527, 65531, 65533, 65534, 65535
+};
+
+/*
+* An array of pointers to CDFs of decorrelated LARs
+*/
+const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] = {
+ WebRtcIsac_kLpcShapeCdfVec01Ub16,
+ WebRtcIsac_kLpcShapeCdfVec1Ub16,
+ WebRtcIsac_kLpcShapeCdfVec2Ub16,
+ WebRtcIsac_kLpcShapeCdfVec3Ub16,
+ WebRtcIsac_kLpcShapeCdfVec4Ub16,
+ WebRtcIsac_kLpcShapeCdfVec5Ub16,
+ WebRtcIsac_kLpcShapeCdfVec6Ub16,
+ WebRtcIsac_kLpcShapeCdfVec7Ub16,
+ WebRtcIsac_kLpcShapeCdfVec8Ub16,
+ WebRtcIsac_kLpcShapeCdfVec01Ub160,
+ WebRtcIsac_kLpcShapeCdfVec01Ub161,
+ WebRtcIsac_kLpcShapeCdfVec01Ub162,
+ WebRtcIsac_kLpcShapeCdfVec01Ub163,
+ WebRtcIsac_kLpcShapeCdfVec01Ub164,
+ WebRtcIsac_kLpcShapeCdfVec01Ub165,
+ WebRtcIsac_kLpcShapeCdfVec01Ub166
+};
+
+/*
+* The smallest reconstruction points for quantiztion of LAR coefficients.
+*/
+const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ -0.8250, -0.9750, -1.1250, -2.1750, -0.9750, -1.1250, -1.4250,
+ -2.6250, -1.4250, -1.2750, -1.8750, -3.6750, -1.7250, -1.8750,
+ -2.3250, -5.4750
+};
+
+/*
+* Number of reconstruction points of quantizers for LAR coefficients.
+*/
+const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 13, 15, 17, 29, 15, 16, 20, 35, 20,
+ 20, 27, 54, 25, 27, 33, 70
+};
+
+/*
+* Starting index for entropy decoder to search for the right interval,
+* one entry per LAR coefficient
+*/
+const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME] =
+{
+ 6, 7, 8, 14, 7, 8, 10, 17, 10,
+ 10, 13, 27, 12, 13, 16, 35
+};
+
+/*
+* LAR quantization step-size.
+*/
+const double WebRtcIsac_kLpcShapeQStepSizeUb16 = 0.150000;
diff --git a/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.h b/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.h
new file mode 100644
index 0000000000..68d08b2047
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_shape_swb16_tables.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_shape_swb16_tables.h
+ *
+ * This file declares tables used for entropy coding of LPC shape of
+ * upper-band signal if the bandwidth is 16 kHz.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
+
+#include "settings.h"
+#include "typedefs.h"
+
+
+extern const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kIintraVecDecorrMatUb16[UB_LPC_ORDER][UB_LPC_ORDER];
+
+extern const double WebRtcIsac_kInterVecDecorrMatUb16
+[UB16_LPC_VEC_PER_FRAME][UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub16[14];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec1Ub16[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec2Ub16[18];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec3Ub16[30];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec4Ub16[16];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec5Ub16[17];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec6Ub16[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec7Ub16[36];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec8Ub16[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub160[21];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub161[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub162[55];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub163[26];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub164[28];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub165[34];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeCdfVec01Ub166[71];
+
+extern const WebRtc_UWord16* WebRtcIsac_kLpcShapeCdfMatUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeLeftRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_Word16 WebRtcIsac_kLpcShapeNumRecPointUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const WebRtc_UWord16 WebRtcIsac_kLpcShapeEntropySearchUb16
+[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+
+extern const double WebRtcIsac_kLpcShapeQStepSizeUb16;
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
diff --git a/src/mod/codecs/mod_isac/lpc_tables.c b/src/mod/codecs/mod_isac/lpc_tables.c
new file mode 100644
index 0000000000..7df6121462
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_tables.c
@@ -0,0 +1,1129 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/* coding tables for the KLT coefficients */
+
+#include "lpc_tables.h"
+#include "settings.h"
+
+/* indices of KLT coefficients used */
+const WebRtc_UWord16 WebRtcIsac_kQKltSelIndGain[12] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltSelIndShape[108] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 104, 105, 106, 107};
+
+/* cdf array for model indicator */
+const WebRtc_UWord16 WebRtcIsac_kQKltModelCdf[4] = {
+ 0, 15434, 37548, 65535};
+
+/* pointer to cdf array for model indicator */
+const WebRtc_UWord16 *WebRtcIsac_kQKltModelCdfPtr[1] = {WebRtcIsac_kQKltModelCdf};
+
+/* initial cdf index for decoder of model indicator */
+const WebRtc_UWord16 WebRtcIsac_kQKltModelInitIndex[1] = {1};
+
+/* offset to go from rounded value to quantization index */
+const short WebRtcIsac_kQKltQuantMinGain[12] = {
+ 3, 6, 4, 6, 6, 9, 5, 16, 11, 34, 32, 47};
+
+
+const short WebRtcIsac_kQKltQuantMinShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 2, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 2, 2, 3, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 4, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
+ 4, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 2, 3, 2, 3, 4, 4, 5, 7, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 6, 7, 11, 9, 13, 12, 26};
+
+/* maximum quantization index */
+const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndGain[12] = {
+ 6, 12, 8, 14, 10, 19, 12, 31, 22, 56, 52, 138};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndShape[108] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 2, 2, 2, 2, 4, 4, 5, 6, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 2, 2,
+ 2, 2, 3, 4, 5, 7, 0, 0, 0, 0,
+ 2, 0, 2, 2, 2, 2, 3, 2, 2, 4,
+ 4, 6, 6, 9, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 3, 2, 4, 4, 7, 7,
+ 9, 13, 0, 0, 2, 2, 2, 2, 2, 2,
+ 3, 4, 5, 4, 6, 8, 8, 10, 16, 25,
+ 0, 2, 2, 4, 5, 4, 4, 4, 7, 8,
+ 9, 10, 13, 19, 17, 23, 25, 49};
+
+/* index offset */
+const WebRtc_UWord16 WebRtcIsac_kQKltOffsetGain[3][12] = {
+{ 0, 7, 20, 29, 44, 55, 75, 88, 120, 143,
+ 200, 253},
+{ 0, 7, 19, 27, 42, 53, 73, 86, 117, 140,
+ 197, 249},
+{ 0, 7, 20, 28, 44, 55, 75, 89, 121, 145,
+ 202, 257}};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltOffsetShape[3][108] = {
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 14, 17, 20, 23, 28, 33, 39, 46, 47,
+ 48, 49, 50, 52, 53, 54, 55, 56, 58, 61,
+ 64, 67, 70, 74, 79, 85, 93, 94, 95, 96,
+ 97, 100, 101, 104, 107, 110, 113, 117, 120, 123,
+ 128, 133, 140, 147, 157, 158, 159, 160, 161, 164,
+ 167, 170, 173, 176, 179, 183, 186, 191, 196, 204,
+ 212, 222, 236, 237, 238, 241, 244, 247, 250, 253,
+ 256, 260, 265, 271, 276, 283, 292, 301, 312, 329,
+ 355, 356, 359, 362, 367, 373, 378, 383, 388, 396,
+ 405, 415, 426, 440, 460, 478, 502, 528},
+{ 0, 1, 2, 3, 4, 6, 7, 8, 9, 11,
+ 13, 16, 19, 22, 26, 29, 34, 39, 45, 46,
+ 47, 48, 49, 50, 51, 52, 53, 55, 57, 60,
+ 63, 66, 70, 73, 78, 84, 91, 92, 93, 94,
+ 95, 96, 97, 99, 102, 105, 108, 111, 114, 118,
+ 123, 128, 134, 141, 151, 152, 153, 154, 156, 159,
+ 162, 165, 168, 171, 174, 177, 181, 186, 194, 200,
+ 208, 218, 233, 234, 235, 236, 239, 242, 245, 248,
+ 251, 254, 258, 263, 270, 277, 288, 297, 308, 324,
+ 349, 351, 354, 357, 361, 366, 372, 378, 383, 390,
+ 398, 407, 420, 431, 450, 472, 496, 524},
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 11,
+ 14, 17, 20, 23, 26, 29, 34, 40, 47, 48,
+ 49, 50, 51, 52, 53, 54, 55, 58, 61, 64,
+ 67, 70, 73, 77, 82, 88, 96, 97, 98, 99,
+ 101, 102, 104, 107, 110, 113, 116, 119, 122, 125,
+ 129, 134, 141, 150, 160, 161, 162, 163, 166, 168,
+ 171, 174, 177, 180, 183, 186, 190, 195, 201, 208,
+ 216, 226, 243, 244, 245, 248, 251, 254, 257, 260,
+ 263, 268, 273, 278, 284, 291, 299, 310, 323, 340,
+ 366, 368, 371, 374, 379, 383, 389, 394, 399, 406,
+ 414, 422, 433, 445, 461, 480, 505, 533}};
+
+/* initial cdf index for KLT coefficients */
+const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexGain[3][12] = {
+{ 3, 6, 4, 7, 5, 10, 6, 16, 11, 28,
+ 26, 69},
+{ 3, 6, 4, 7, 5, 10, 6, 15, 11, 28,
+ 26, 69},
+{ 3, 6, 4, 8, 5, 10, 7, 16, 12, 28,
+ 27, 70}};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexShape[3][108] = {
+{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 2, 2, 3, 3, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 0,
+ 1, 0, 1, 1, 1, 1, 2, 1, 1, 2,
+ 2, 3, 3, 5, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 2, 1, 2, 2, 4, 4,
+ 5, 7, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 3, 2, 3, 4, 4, 5, 8, 13,
+ 0, 1, 1, 2, 3, 2, 2, 2, 4, 4,
+ 5, 5, 7, 10, 9, 12, 13, 25},
+{ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 1, 1, 1, 2, 1, 2, 2, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 2, 1, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 2, 2,
+ 2, 3, 3, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 4, 3, 4,
+ 5, 7, 0, 0, 0, 1, 1, 1, 1, 1,
+ 1, 2, 2, 3, 3, 5, 4, 5, 8, 12,
+ 1, 1, 1, 2, 2, 3, 3, 2, 3, 4,
+ 4, 6, 5, 9, 11, 12, 14, 25},
+{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 1, 1, 1, 2, 3, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 2, 2, 3, 4, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 3, 4, 5, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 3, 3, 4,
+ 5, 8, 0, 0, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 3, 3, 4, 5, 6, 8, 13,
+ 1, 1, 1, 2, 2, 3, 2, 2, 3, 4,
+ 4, 5, 6, 8, 9, 12, 14, 25}};
+
+/* offsets for quantizer representation levels*/
+const WebRtc_UWord16 WebRtcIsac_kQKltOfLevelsGain[3] = {
+ 0, 392, 779};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltOfLevelsShape[3] = {
+ 0, 578, 1152};
+
+/* quantizer representation levels */
+const double WebRtcIsac_kQKltLevelsGain[1176] = {
+-2.78127126, -1.76745590, -0.77913790, -0.00437329, 0.79961206, 1.81775776, 2.81389782, -5.78753143, -4.88384084, -3.89320940,
+-2.88133610, -1.92859977, -0.86347396, 0.02003888, 0.86140400, 1.89667156, 2.97134967, 3.98781964, 4.91727277, 5.82865898,
+-4.11195874, -2.80898424, -1.87547977, -0.80943825, -0.00679084, 0.79573851, 1.83953397, 2.67586037, 3.76274082, -6.10933968,
+-4.93034581, -3.89281296, -2.91530625, -1.89684163, -0.85319130, -0.02275767, 0.86862017, 1.91578276, 2.96107339, 3.96543056,
+ 4.91369908, 5.91058154, 6.83848343, 8.07136925, -5.87470395, -4.84703049, -3.84284597, -2.86168446, -1.89290192, -0.82798145,
+-0.00080013, 0.82594974, 1.85754329, 2.88351798, 3.96172628, -8.85684885, -7.87387461, -6.97811862, -5.93256270, -4.94301439,
+-3.95513701, -2.96041544, -1.94031192, -0.87961478, -0.00456201, 0.89911505, 1.91723376, 2.94011511, 3.93302540, 4.97990967,
+ 5.93133404, 7.02181199, 7.92407762, 8.80155440, 10.04665814, -4.82396678, -3.85612158, -2.89482244, -1.89558408, -0.90036978,
+-0.00677823, 0.90607989, 1.90937981, 2.91175777, 3.91637730, 4.97565723, 5.84771228, 7.11145863, -16.07879840, -15.03776309,
+-13.93905670, -12.95671800, -11.89171202, -10.95820934, -9.95923714, -8.94357334, -7.99068299, -6.97481009, -5.94826231, -4.96673988,
+-3.97490466, -2.97846970, -1.95130435, -0.94215262, -0.01444043, 0.96770704, 1.95848598, 2.94107862, 3.95666119, 4.97253085,
+ 5.97191122, 6.93277360, 7.96608727, 8.87958779, 10.00264269, 10.86560820, 12.07449071, 13.04491775, 13.97507061, 14.91845261,
+-10.85696295, -9.83365357, -9.01245635, -7.95915145, -6.95625003, -5.95362618, -4.93468444, -3.98760978, -2.95044407, -1.97041277,
+-0.97701799, -0.00840234, 0.97834289, 1.98361415, 2.97802439, 3.96415871, 4.95369042, 5.94101770, 6.92756798, 7.94063998,
+ 8.85951828, 9.97077022, 11.00068503, -33.92030406, -32.81426422, -32.00000000, -31.13243639, -30.11886909, -29.06017570, -28.12598824,
+-27.22045482, -25.81215858, -25.07849962, -23.93018013, -23.02097643, -21.89529725, -20.99091085, -19.98889048, -18.94327044, -17.96562071,
+-16.96126218, -15.95054062, -14.98516200, -13.97101012, -13.02106500, -11.98438006, -11.03216748, -9.95930286, -8.97043946, -7.98085082,
+-6.98360995, -5.98998802, -4.98668173, -4.00032906, -3.00420619, -1.98701132, -0.99324682, -0.00609324, 0.98297834, 1.99483076,
+ 3.00305044, 3.97142097, 4.97525759, 5.98612258, 6.97448236, 7.97575900, 9.01086211, 9.98665542, 11.00541438, 11.98078628,
+ 12.92352471, 14.06849675, 14.99949430, 15.94904834, 16.97440321, 18.04040916, 18.88987609, 20.05312391, 21.00000000, 21.79443341,
+-31.98578825, -31.00000000, -29.89060567, -28.98555686, -27.97114102, -26.84935410, -26.02402230, -24.94195278, -23.92336849, -22.95552382,
+-21.97932836, -20.96055470, -19.99649553, -19.03436122, -17.96706525, -17.01139515, -16.01363516, -14.99154248, -14.00298333, -12.99630613,
+-11.99955519, -10.99000421, -10.00819092, -8.99763648, -7.98431793, -7.01769025, -5.99604690, -4.99980697, -3.99334671, -3.01748192,
+-2.02051217, -1.00848371, -0.01942358, 1.00477757, 1.95477872, 2.98593031, 3.98779079, 4.96862849, 6.02694771, 6.93983733,
+ 7.89874717, 8.99615862, 10.02367921, 10.96293452, 11.84351528, 12.92207187, 13.85122329, 15.05146877, 15.99371264, 17.00000000,
+ 18.00000000, 19.00000000, 19.82763573, -47.00000000, -46.00000000, -44.87138498, -44.00000000, -43.00000000, -42.00000000, -41.00000000,
+-39.88966612, -38.98913239, -37.80306486, -37.23584325, -35.94200288, -34.99881301, -34.11361858, -33.06507360, -32.13129135, -30.90891364,
+-29.81511907, -28.99250380, -28.04535391, -26.99767800, -26.04418164, -24.95687851, -24.04865595, -23.03392645, -21.89366707, -20.93517364,
+-19.99388660, -18.91620943, -18.03749683, -16.99532379, -15.98683813, -15.06421479, -13.99359211, -12.99714098, -11.97022520, -10.98500279,
+-9.98834422, -8.95729330, -8.01232284, -7.00253661, -5.99681626, -5.01207817, -3.95914904, -3.01232178, -1.96615919, -0.97687670,
+ 0.01228030, 0.98412288, 2.01753544, 3.00580570, 3.97783510, 4.98846894, 6.01321400, 7.00867732, 8.00416375, 9.01771966,
+ 9.98637729, 10.98255180, 11.99194163, 13.01807333, 14.00999545, 15.00118556, 16.00089224, 17.00584148, 17.98251763, 18.99942091,
+ 19.96917690, 20.97839265, 21.98207297, 23.00171271, 23.99930737, 24.99746061, 26.00936304, 26.98240132, 28.01126868, 29.01395915,
+ 29.98153507, 31.01376711, 31.99876818, 33.00475317, 33.99753994, 34.99493913, 35.98933585, 36.95620160, 37.98428461, 38.99317544,
+ 40.01832073, 40.98048133, 41.95999283, 42.98232091, 43.96523612, 44.99574268, 45.99524194, 47.05464025, 48.03821548, 48.99354366,
+ 49.96400411, 50.98017973, 51.95184408, 52.96291806, 54.00194392, 54.96603783, 55.95623778, 57.03076595, 58.05889901, 58.99081551,
+ 59.97928121, 61.05071612, 62.03971580, 63.01286038, 64.01290338, 65.02074503, 65.99454594, 67.00399425, 67.96571257, 68.95305727,
+ 69.92030664, 70.95594862, 71.98088567, 73.04764124, 74.00285480, 75.02696330, 75.89837673, 76.93459997, 78.16266309, 78.83317543,
+ 80.00000000, 80.87251574, 82.09803524, 83.10671664, 84.00000000, 84.77023523, 86.00000000, 87.00000000, 87.92946897, 88.69159118,
+ 90.00000000, 90.90535270, -3.00000000, -2.00000000, -0.77592424, -0.00564307, 0.76727305, 2.00000000, 3.00000000, -6.00000000,
+-5.00000000, -4.00000000, -2.92897924, -1.85623684, -0.72445303, -0.00119184, 0.72896652, 2.05710416, 3.17909894, 4.00000000,
+ 5.00000000, -3.00000000, -2.00000000, -0.67480586, -0.00028016, 0.66618169, 2.00000000, 3.00000000, 4.00000000, -7.00000000,
+-6.00000000, -5.00000000, -3.78336783, -2.84811556, -2.04088844, -0.71114371, 0.03142493, 0.69662772, 1.91417930, 3.00000000,
+ 4.01411062, 5.00000000, 6.00000000, 7.00000000, -6.00000000, -5.00000000, -4.00000000, -3.00000000, -2.00000000, -0.63703469,
+ 0.00169604, 0.66294191, 1.83808563, 3.00000000, 4.00000000, -8.00000000, -7.00000000, -6.03082300, -5.00000000, -3.88061019,
+-2.92670084, -1.99902336, -0.72898996, -0.02880170, 0.73769927, 1.95920233, 2.78356263, 4.08100921, 5.00000000, 6.00000000,
+ 6.78771437, 8.00000000, 9.00000000, 10.00000000, 11.00000000, -5.00000000, -4.00000000, -2.88150384, -1.89520024, -0.71479482,
+ 0.00962397, 0.72816030, 1.73583550, 3.00000000, 4.00000000, 5.00000000, 6.00000000, 7.00000000, -16.00000000, -15.00000000,
+-13.80516401, -13.00000000, -12.00000000, -11.00000000, -10.02723144, -9.11825995, -8.05820112, -7.00000000, -6.17943541, -5.01837980,
+-3.97546169, -2.92806857, -1.89778775, -0.81138893, -0.02246016, 0.80528415, 1.85705214, 2.96438524, 3.97540151, 4.79684246,
+ 6.00000000, 6.75549513, 8.12185828, 9.00000000, 10.00000000, 11.00000000, 12.00000000, 13.00000000, 14.00000000, -11.00000000,
+-10.00000000, -9.00000000, -7.91603344, -6.77865892, -5.85765006, -4.93342332, -3.96679157, -2.84925552, -1.89230732, -0.85384229,
+ 0.00579591, 0.84863246, 1.89006713, 2.89483818, 3.87322971, 5.13228411, 6.00000000, 7.00000000, 8.00000000, 9.00000000,
+ 10.00000000, 11.00000000, -34.00000000, -33.00000000, -32.00000000, -31.00000000, -30.00000000, -29.00000000, -28.00000000, -27.00000000,
+-26.00000000, -25.00000000, -24.00000000, -23.00000000, -22.00000000, -21.00000000, -20.19501953, -19.00000000, -18.00000000, -17.00000000,
+-16.00000000, -14.89069633, -14.00000000, -13.00000000, -12.16260304, -11.15418282, -9.83543570, -8.85600407, -7.82712677, -7.05664308,
+-5.97007352, -4.89268438, -3.93822771, -2.94975269, -1.92192127, -0.90702480, 0.03974847, 0.92488359, 1.93747579, 2.94500522,
+ 3.95181797, 4.95433087, 5.95141808, 7.00212920, 8.02964757, 9.03210585, 9.84644504, 10.82907720, 11.87622530, 12.96908371,
+ 14.00000000, 15.16963413, 15.94902025, 17.00000000, 18.00000000, 19.00000000, 20.00000000, 21.00000000, 22.00000000, -29.00000000,
+-27.79780781, -27.00757888, -26.01571026, -24.89695568, -23.99946491, -22.98699614, -21.96678139, -20.99883532, -20.00851529, -18.94738054,
+-17.98672566, -16.98684787, -15.96917397, -14.99856852, -13.98974852, -12.97786927, -11.96110939, -10.98877093, -9.99875257, -8.99001359,
+-8.00799989, -6.99471760, -6.00034670, -4.99936372, -4.00581479, -3.00424577, -2.02047620, -0.99713266, -0.00366397, 1.00803955,
+ 1.98452687, 3.00748501, 4.02714611, 4.97661026, 5.99337271, 6.99754716, 8.00713602, 8.97184974, 9.98047901, 10.97685939,
+ 11.99533975, 12.96107876, 13.95061478, 15.00756776, 15.94078690, 16.88231059, 17.92069248, 18.78011047, 20.00000000, 21.00000000,
+ 22.00000000, -55.76988333, -54.96048193, -53.88411581, -52.94117980, -51.80983449, -50.90359699, -50.00000000, -48.99838741, -47.97685542,
+-47.03288597, -45.97820919, -45.02418374, -43.90081897, -42.88832512, -41.98234549, -40.96745512, -39.98148729, -39.06792854, -37.96493755,
+-36.98707870, -36.03416079, -35.01192444, -33.95785029, -32.99469087, -31.96633807, -31.01769053, -29.99727691, -28.99329690, -27.98873019,
+-27.00344273, -25.97657141, -25.00511074, -23.96689479, -23.01566842, -22.01632643, -21.00076343, -19.97788007, -18.97248680, -17.96076284,
+-16.97585453, -15.98345587, -15.01612745, -13.96862118, -12.96622055, -12.02196641, -11.02078103, -9.98445656, -9.00050060, -8.03442387,
+-7.00363761, -5.97921358, -4.98886269, -4.00528221, -3.01672947, -1.98599795, -1.00668518, -0.02633490, 1.00794139, 2.00837138,
+ 2.99213287, 3.98710216, 4.99064334, 6.01416391, 7.01759708, 7.97878151, 8.99665730, 10.02656114, 11.01863887, 12.01207901,
+ 13.00958725, 13.99237829, 15.00954971, 16.00724653, 17.00606559, 17.99886292, 18.99611967, 19.98808171, 21.01871930, 21.97014763,
+ 22.99833843, 24.00316842, 24.99949142, 25.98539601, 27.02480733, 27.98075377, 28.98266019, 30.00611445, 30.99409128, 31.94523141,
+ 32.97688339, 33.98800206, 35.00177074, 35.98639997, 36.98939428, 37.95644255, 39.00114054, 39.99492439, 40.99338254, 41.97050844,
+ 43.03085663, 43.96757668, 44.97800970, 45.95953358, 46.98109551, 47.99368477, 49.00141209, 49.94459923, 50.93298108, 51.99894661,
+ 53.06463883, 53.99704669, 55.02037199, 55.98368047, 57.01930954, 58.03813852, 58.96232502, 60.01644186, 61.03254711, 62.01086576,
+ 62.87962247, 63.98378413, 65.02189831, 65.93003954, 66.92439900, 68.07051633, 68.95928756, 70.03315022, 71.05579859, 72.00000000,
+ 73.00000000, 74.00000000, 75.00000000, 75.93485291, 77.20950456, 78.00000000, 79.00000000, 79.91519960, 81.00000000, -3.00000000,
+-2.00000000, -0.65174074, -0.00092112, 0.62967387, 2.00000000, 3.00000000, -6.00000000, -5.00000000, -4.00000000, -2.89861729,
+-1.69999061, -0.72632201, 0.00219241, 0.72891750, 1.73257865, 3.00000000, 3.76561508, 5.00000000, 6.00000000, -3.00000000,
+-2.00000000, -0.66227013, 0.00389373, 0.66163500, 2.00000000, 3.00000000, 4.00000000, -8.00000000, -7.00000000, -6.00000000,
+-4.76421796, -4.04320264, -3.01415201, -1.84346485, -0.77185048, 0.00061977, 0.76274524, 1.84330156, 3.00000000, 4.00000000,
+ 5.00000000, 6.00000000, 7.00000000, -6.00000000, -5.00000000, -4.00000000, -3.00000000, -1.75749611, -0.72951347, -0.00104394,
+ 0.72040315, 1.72594036, 3.00000000, 4.00000000, -9.00000000, -8.00000000, -7.00000000, -5.90394062, -5.00000000, -3.75562807,
+-2.89699407, -1.86696610, -0.79056636, -0.00330943, 0.79744554, 1.85149941, 2.91118681, 3.99520311, 4.96341987, 6.00000000,
+ 7.00000000, 8.00000000, 9.00000000, 10.00000000, -6.00000000, -4.80151529, -4.00000000, -2.87442856, -1.85285815, -0.77767592,
+-0.02071301, 0.81752572, 1.82503940, 2.79602150, 3.92870203, 5.00000000, 6.00000000, 7.00000000, -17.00000000, -16.00000000,
+-15.00000000, -14.00000000, -13.00000000, -12.00000000, -11.00000000, -9.80059874, -9.00000000, -8.00185204, -7.13087808, -5.92942149,
+-4.77883243, -3.93417708, -2.88004618, -1.89952522, -0.86239337, 0.00332274, 0.86657548, 1.89479279, 2.89701813, 3.90987417,
+ 4.98910145, 6.07676766, 7.00000000, 8.00000000, 9.00000000, 10.00000000, 11.00000000, 12.00000000, 13.00000000, 14.00000000,
+-12.00000000, -11.00000000, -9.89996262, -8.85894205, -7.87594823, -6.99685317, -5.94917589, -4.93914916, -3.93317670, -2.93174244,
+-1.90737478, -0.90982242, 0.00803316, 0.90111563, 1.90362879, 2.90332432, 3.90654662, 4.94461954, 5.87963665, 6.91988113,
+ 7.79514004, 8.98805413, 10.00000000, 11.00000000, -35.00000000, -34.00000000, -33.00000000, -32.00000000, -31.00000000, -30.00000000,
+-29.00000000, -28.00000000, -27.00000000, -26.00000000, -25.00000000, -24.00000000, -22.88310970, -22.00000000, -21.00000000, -20.00000000,
+-19.00000000, -18.00000000, -17.00000000, -16.11854974, -15.00000000, -14.10507667, -13.04497040, -11.94846700, -10.97432494, -9.94514368,
+-8.97311414, -7.94171496, -6.97232122, -5.98590548, -4.97455572, -3.95477903, -2.93935454, -1.95573532, -0.97120273, -0.02084826,
+ 0.95689153, 1.96679781, 2.97060165, 3.96660892, 4.96754331, 5.97996089, 6.93822411, 7.96618014, 8.95809791, 9.98891474,
+ 10.95713402, 11.85433084, 13.03831696, 13.84035295, 15.00729606, 15.98652872, 17.20557599, 18.00000000, 18.90794805, 20.00000000,
+ 21.00000000, -34.00000000, -33.00000000, -32.00000000, -31.00000000, -30.00000000, -28.97280602, -28.00000000, -27.16255057, -26.04078092,
+-24.85442050, -24.15783484, -22.78614956, -21.95739865, -21.21844626, -20.03008104, -19.03888543, -17.90460490, -17.02064693, -15.84673652,
+-14.87140709, -13.87996048, -12.94907251, -11.96795995, -11.00977925, -9.95103238, -8.96674655, -7.96351667, -6.96886200, -5.99335494,
+-4.97515534, -3.98891694, -2.99581150, -1.98758360, -0.99249128, -0.00001403, 0.98807868, 1.99119869, 2.99019366, 3.98612953,
+ 5.00312941, 5.98833080, 6.99686651, 7.98373889, 8.97942222, 9.94202752, 10.99671622, 11.94306164, 12.98539825, 13.90728690,
+ 14.89907642, 15.94836675, 16.89611342, 17.84084949, 18.74910958, 20.00000000, -67.00000000, -66.00000000, -65.00000000, -64.00000000,
+-63.02511977, -62.00000000, -61.06061493, -59.95964043, -59.12824439, -58.00000000, -57.00000000, -56.00000000, -54.87857996, -54.09689334,
+-53.00000000, -52.21057366, -50.93867921, -50.03032952, -49.19283867, -47.89439051, -46.99505692, -46.04895543, -44.89687413, -43.78942208,
+-42.99025156, -41.88436155, -40.99169704, -40.00320429, -38.90181498, -38.06029271, -37.05030818, -36.07554573, -35.03202233, -33.93117946,
+-32.97736655, -31.98942819, -30.99546798, -30.01511004, -28.97296525, -28.02561164, -26.94386985, -25.99632704, -25.00461143, -24.01578192,
+-22.99177609, -22.02261094, -20.97939001, -19.96176066, -19.00442980, -18.01529434, -17.00196902, -15.99794828, -14.98675055, -13.97517657,
+-12.98676283, -11.99718760, -11.00167809, -9.98872268, -9.02138474, -8.00320338, -6.99542797, -6.00059136, -5.01311763, -4.00336943,
+-3.00348281, -1.99365875, -0.98223019, 0.00126343, 0.99699237, 1.99381968, 3.00054436, 3.99898305, 5.00160508, 6.00310399,
+ 6.99885096, 8.02740039, 8.99515550, 9.98962151, 11.00642302, 11.98694516, 13.00018933, 13.97726018, 14.99186645, 16.00580131,
+ 16.97434224, 17.96982658, 19.00066438, 20.01228749, 21.00741822, 21.94988312, 23.00860212, 23.98801542, 24.97638417, 25.98003521,
+ 27.02336188, 27.99667029, 29.01014125, 30.02481912, 31.01415797, 31.97399854, 33.06214485, 33.99929330, 34.94095386, 35.96368372,
+ 36.96980925, 37.98389244, 39.01121235, 40.00715026, 41.06382894, 41.96618280, 43.01555590, 43.95430436, 45.01970038, 45.99967821,
+ 47.19847394, 48.04852502, 49.10609965, 50.04244122, 50.86051406, 51.92983796, 53.02781107, 54.06248545, 54.89942009, 56.08347165,
+ 57.06887956, 58.09671115, 59.07832400, 59.87005277, 61.14778499, 62.00000000, 63.00000000, 64.00000000, 65.00000000, 66.00000000,
+ 67.00000000, 68.00000000, 69.00000000, 70.00000000, 71.00000000, 72.00000000};
+
+const double WebRtcIsac_kQKltLevelsShape[1735] = {
+ 0.00032397, 0.00008053, -0.00061202, -0.00012620, 0.00030437, 0.00054764, -0.00027902, 0.00069360, 0.00029449, -0.80219239,
+ 0.00091089, -0.74514927, -0.00094283, 0.64030631, -0.60509119, 0.00035575, 0.61851665, -0.62129957, 0.00375219, 0.60054900,
+-0.61554359, 0.00054977, 0.63362016, -1.73118727, -0.65422341, 0.00524568, 0.66165298, 1.76785515, -1.83182018, -0.65997434,
+-0.00011887, 0.67524299, 1.79933938, -1.76344480, -0.72547708, -0.00133017, 0.73104704, 1.75305377, 2.85164534, -2.80423916,
+-1.71959639, -0.75419722, -0.00329945, 0.77196760, 1.72211069, 2.87339653, 0.00031089, -0.00015311, 0.00018201, -0.00035035,
+-0.77357251, 0.00154647, -0.00047625, -0.00045299, 0.00086590, 0.00044762, -0.83383829, 0.00024787, -0.68526258, -0.00122472,
+ 0.64643255, -0.60904942, -0.00448987, 0.62309184, -0.59626442, -0.00574132, 0.62296546, -0.63222115, 0.00013441, 0.63609545,
+-0.66911055, -0.00369971, 0.66346095, 2.07281301, -1.77184694, -0.67640425, -0.00010145, 0.64818392, 1.74948973, -1.69420224,
+-0.71943894, -0.00004680, 0.75303493, 1.81075983, 2.80610041, -2.80005755, -1.79866753, -0.77409777, -0.00084220, 0.80141293,
+ 1.78291081, 2.73954236, 3.82994169, 0.00015140, -0.00012766, -0.00034241, -0.00119125, -0.76113497, 0.00069246, 0.76722027,
+ 0.00132862, -0.69107530, 0.00010656, 0.77061578, -0.78012970, 0.00095947, 0.77828502, -0.64787758, 0.00217168, 0.63050167,
+-0.58601125, 0.00306596, 0.59466308, -0.58603410, 0.00059779, 0.64257970, 1.76512766, -0.61193600, -0.00259517, 0.59767574,
+-0.61026273, 0.00315811, 0.61725479, -1.69169719, -0.65816029, 0.00067575, 0.65576890, 2.00000000, -1.72689193, -0.69780808,
+-0.00040990, 0.70668487, 1.74198458, -3.79028154, -3.00000000, -1.73194459, -0.70179341, -0.00106695, 0.71302629, 1.76849782,
+-2.89332364, -1.78585007, -0.78731491, -0.00132610, 0.79692976, 1.75247009, 2.97828682, -5.26238694, -3.69559829, -2.87286122,
+-1.84908818, -0.84434577, -0.01167975, 0.84641753, 1.84087672, 2.87628156, 3.83556679, -0.00190204, 0.00092642, 0.00354385,
+-0.00012982, -0.67742785, 0.00229509, 0.64935672, -0.58444751, 0.00470733, 0.57299534, -0.58456202, -0.00097715, 0.64593607,
+-0.64060330, -0.00638534, 0.59680157, -0.59287537, 0.00490772, 0.58919707, -0.60306173, -0.00417464, 0.60562100, -1.75218757,
+-0.63018569, -0.00225922, 0.63863300, -0.63949939, -0.00126421, 0.64268914, -1.75851182, -0.68318060, 0.00510418, 0.69049211,
+ 1.88178506, -1.71136148, -0.72710534, -0.00815559, 0.73412917, 1.79996711, -2.77111145, -1.73940498, -0.78212945, 0.01074476,
+ 0.77688916, 1.76873972, 2.87281379, 3.77554698, -3.75832725, -2.95463235, -1.80451491, -0.80017226, 0.00149902, 0.80729206,
+ 1.78265046, 2.89391793, -3.78236148, -2.83640598, -1.82532067, -0.88844327, -0.00620952, 0.88208030, 1.85757631, 2.81712391,
+ 3.88430176, 5.16179367, -7.00000000, -5.93805408, -4.87172597, -3.87524433, -2.89399744, -1.92359563, -0.92136341, -0.00172725,
+ 0.93087018, 1.90528280, 2.89809686, 3.88085708, 4.89147740, 5.89078692, -0.00239502, 0.00312564, -1.00000000, 0.00178325,
+ 1.00000000, -0.62198029, 0.00143254, 0.65344051, -0.59851220, -0.00676987, 0.61510140, -0.58894151, 0.00385055, 0.59794203,
+-0.59808568, -0.00038214, 0.57625703, -0.63009713, -0.01107985, 0.61278758, -0.64206758, -0.00154369, 0.65480598, 1.80604162,
+-1.80909286, -0.67810514, 0.00205762, 0.68571097, 1.79453891, -3.22682422, -1.73808453, -0.71870305, -0.00738594, 0.71486172,
+ 1.73005326, -1.66891897, -0.73689615, -0.00616203, 0.74262409, 1.73807899, -2.92417482, -1.73866741, -0.78133871, 0.00764425,
+ 0.80027264, 1.78668732, 2.74992588, -4.00000000, -2.75578740, -1.83697516, -0.83117035, -0.00355191, 0.83527172, 1.82814700,
+ 2.77377675, 3.80718693, -3.81667698, -2.83575471, -1.83372350, -0.86579471, 0.00547578, 0.87582281, 1.82858793, 2.87265007,
+ 3.91405377, -4.87521600, -3.78999094, -2.86437014, -1.86964365, -0.90618018, 0.00128243, 0.91497811, 1.87374952, 2.83199819,
+ 3.91519130, 4.76632822, -6.68713448, -6.01252467, -4.94587936, -3.88795368, -2.91299088, -1.92592211, -0.95504570, -0.00089980,
+ 0.94565200, 1.93239633, 2.91832808, 3.91363475, 4.88920034, 5.96471415, 6.83905252, 7.86195009, 8.81571018, -12.96141759,
+-11.73039516, -10.96459719, -9.97382433, -9.04414433, -7.89460619, -6.96628608, -5.93236595, -4.93337924, -3.95479990, -2.96451499,
+-1.96635876, -0.97271229, -0.00402238, 0.98343930, 1.98348291, 2.96641164, 3.95456471, 4.95517089, 5.98975714, 6.90322073,
+ 7.90468849, 8.85639467, 9.97255498, 10.79006309, 11.81988596, 0.04950500, -1.00000000, -0.01226628, 1.00000000, -0.59479469,
+-0.10438305, 0.59822144, -2.00000000, -0.67109149, -0.09256692, 0.65171621, 2.00000000, -3.00000000, -1.68391999, -0.76681039,
+-0.03354151, 0.71509146, 1.77615472, -2.00000000, -0.68661511, -0.02497881, 0.66478398, 2.00000000, -2.00000000, -0.67032784,
+-0.00920582, 0.64892756, 2.00000000, -2.00000000, -0.68561894, 0.03641869, 0.73021611, 1.68293863, -4.00000000, -2.72024184,
+-1.80096059, -0.81696185, 0.03604685, 0.79232033, 1.70070730, 3.00000000, -4.00000000, -2.71795670, -1.80482986, -0.86001162,
+ 0.03764903, 0.87723968, 1.79970771, 2.72685932, 3.67589143, -5.00000000, -4.00000000, -2.85492548, -1.78996365, -0.83250358,
+-0.01376828, 0.84195506, 1.78161105, 2.76754458, 4.00000000, -6.00000000, -5.00000000, -3.82268811, -2.77563624, -1.82608163,
+-0.86486114, -0.02671886, 0.86693165, 1.88422879, 2.86248347, 3.95632216, -7.00000000, -6.00000000, -5.00000000, -3.77533988,
+-2.86391432, -1.87052039, -0.90513658, 0.06271236, 0.91083620, 1.85734756, 2.86031688, 3.82019418, 4.94420394, 6.00000000,
+-11.00000000, -10.00000000, -9.00000000, -8.00000000, -6.91952415, -6.00000000, -4.92044374, -3.87845165, -2.87392362, -1.88413020,
+-0.91915740, 0.00318517, 0.91602800, 1.89664838, 2.88925058, 3.84123856, 4.78988651, 5.94526812, 6.81953917, 8.00000000,
+-9.00000000, -8.00000000, -7.03319143, -5.94530963, -4.86669720, -3.92438007, -2.88620396, -1.92848070, -0.94365985, 0.01671855,
+ 0.97349410, 1.93419878, 2.89740109, 3.89662823, 4.83235583, 5.88106535, 6.80328232, 8.00000000, -13.00000000, -12.00000000,
+-11.00000000, -10.00000000, -9.00000000, -7.86033489, -6.83344055, -5.89844215, -4.90811454, -3.94841298, -2.95820490, -1.98627966,
+-0.99161468, -0.02286136, 0.96055651, 1.95052433, 2.93969396, 3.94304346, 4.88522624, 5.87434241, 6.78309433, 7.87244101,
+ 9.00000000, 10.00000000, -12.09117356, -11.00000000, -10.00000000, -8.84766108, -7.86934236, -6.98544896, -5.94233429, -4.95583292,
+-3.95575986, -2.97085529, -1.98955811, -0.99359873, -0.00485413, 0.98298870, 1.98093258, 2.96430203, 3.95540216, 4.96915010,
+ 5.96775124, 6.99236918, 7.96503302, 8.99864542, 9.85857723, 10.96541926, 11.91647197, 12.71060069, -26.00000000, -25.00000000,
+-24.00585596, -23.11642573, -22.14271284, -20.89800711, -19.87815799, -19.05036354, -17.88555651, -16.86471209, -15.97711073, -14.94012359,
+-14.02661226, -12.98243228, -11.97489256, -10.97402777, -9.96425624, -9.01085220, -7.97372506, -6.98795002, -5.97271328, -5.00191694,
+-3.98055849, -2.98458048, -1.99470442, -0.99656768, -0.00825666, 1.00272004, 1.99922218, 2.99357669, 4.01407905, 5.01003897,
+ 5.98115528, 7.00018958, 8.00338125, 8.98981046, 9.98990318, 10.96341479, 11.96866930, 12.99175139, 13.94580443, 14.95745083,
+ 15.98992869, 16.97484646, 17.99630043, 18.93396897, 19.88347741, 20.96532482, 21.92191032, 23.22314702, 0.00006846, 0.00014352,
+-0.00056203, 0.00027588, -0.00147678, 1.00000000, 0.00003823, 0.00001975, -0.00033710, -0.00096712, 1.00000000, -1.00000000,
+ 0.00067511, -1.00000000, 0.00342065, 1.00000000, -1.00000000, 0.00196254, 1.00000000, -1.00000000, 0.00201173, 1.00000000,
+-2.00000000, -1.00000000, -0.00381686, 1.00000000, -1.00000000, 0.00178037, 1.00000000, -2.00000000, -1.00000000, -0.00320274,
+ 1.00000000, 2.00000000, -2.00000000, -1.00000000, 0.00426519, 1.00000000, 2.00000000, -3.00000000, -2.00000000, -1.00000000,
+-0.00074072, 0.64654602, 2.00000000, 0.00031217, 0.00063348, 0.00020247, 0.00047891, 0.00122893, -0.00150669, -0.00148276,
+ 0.00016848, 0.00147085, 1.00000000, -0.00088160, 1.00000000, -1.00000000, 0.00381641, 1.00000000, -1.00000000, 0.00129816,
+ 1.00000000, -1.00000000, 0.00074903, 1.00000000, -2.00000000, -0.76230566, -0.00370764, 0.82467977, -0.78769346, -0.00492670,
+ 0.84532630, -2.00000000, -0.70943195, -0.01257613, 0.75905385, 2.00000000, -2.00000000, -0.62780445, -0.00408633, 0.60272506,
+ 2.00000000, 3.00000000, -3.00000000, -2.00000000, -0.61412985, 0.00102833, 0.61527589, 2.00000000, 3.00000000, 0.00012115,
+-0.00080909, 0.00071061, -0.00227957, 0.00179794, 0.00103827, -1.00000000, 0.00444757, -1.00000000, 0.00604068, 1.00000000,
+-1.00000000, 0.00427327, 1.00000000, -1.00000000, 0.00086662, 1.00000000, -1.00000000, -0.00837492, 1.00000000, -0.65715934,
+-0.00645342, 0.64004630, -2.00000000, -0.64987682, -0.01449567, 0.69893373, -2.00000000, -0.63221961, 0.00421765, 0.62452105,
+ 2.00000000, -2.00000000, -0.60027006, -0.00110630, 0.62033821, 2.00000000, -2.00000000, -0.59823932, 0.00928313, 0.62188520,
+ 2.00000000, 3.00000000, -3.00000000, -2.00000000, -0.63230286, -0.00248555, 0.62632575, 2.00000000, 3.00000000, -5.00000000,
+-4.00000000, -3.00000000, -2.00000000, -0.66521143, 0.00544305, 0.66930486, 2.00000000, 3.00000000, 4.00000000, 0.00077008,
+ 0.00061140, -0.00009317, -0.00049643, 1.00000000, -1.00000000, -0.00285084, 1.00000000, -1.00000000, 0.00601784, 1.00000000,
+-1.00000000, -0.00091887, 0.75122772, -0.71579859, -0.00043545, 1.00000000, -0.85571363, -0.00227654, 0.63816873, -1.00000000,
+-0.00393484, 0.76748004, -0.58223659, -0.01229777, 0.58080322, -0.61945902, -0.00232238, 0.62277938, 2.00000000, -2.00000000,
+-0.60595489, -0.00535702, 0.60547736, 2.00000000, -4.00000000, -3.00000000, -2.00000000, -0.62368122, 0.01112097, 0.63997294,
+ 2.00000000, 3.00000000, -3.00000000, -2.00000000, -0.64318217, 0.00515139, 0.64781184, 2.00000000, -3.00000000, -1.78031579,
+-0.67122588, 0.02153711, 0.67899877, 2.00000000, 3.00000000, 4.00000000, -4.00000000, -3.00000000, -1.80503233, -0.69835727,
+-0.00270770, 0.70999554, 1.77332849, 3.00000000, 4.00000000, 5.00000000, -8.00000000, -7.00000000, -6.00000000, -5.00000000,
+-4.00000000, -2.81600693, -1.72970368, -0.73779413, -0.01384841, 0.75694606, 1.80042618, 3.00000000, 4.00000000, 5.00000000,
+ 6.00000000, -0.00051787, 0.00059593, -0.00023319, -1.00000000, 0.00191861, 0.79547197, -0.75020995, 0.00217840, 0.69165833,
+-1.00000000, -0.00304964, 0.67698951, -0.64516943, -0.00657667, 0.59260129, -0.62819301, -0.00456626, 0.59426260, -0.60909519,
+ 0.00256476, 0.61660408, -0.66560131, -0.00293463, 0.67477566, 2.00000000, -2.00000000, -0.62484067, 0.00505116, 0.63491494,
+ 2.00000000, -3.00000000, -2.00000000, -0.68427246, 0.00924353, 0.68755774, 2.00000000, 3.00000000, -3.00000000, -2.00000000,
+-0.65390928, 0.01008025, 0.65849449, 2.00000000, 3.00000000, -5.00000000, -4.00000000, -3.00000000, -1.70848232, -0.72079538,
+-0.00007674, 0.71556176, 1.76815351, 3.00000000, 4.00000000, 5.00000000, -4.00000000, -3.00000000, -1.82887466, -0.73529886,
+ 0.00033458, 0.73847588, 1.83009515, 3.00000000, 4.00000000, -5.00000000, -4.00000000, -2.83203553, -1.79500085, -0.77452749,
+-0.00614320, 0.77416943, 1.82469471, 2.77034612, 4.00000000, 5.00000000, -7.00000000, -6.00000000, -5.00000000, -4.00000000,
+-2.76574798, -1.84700836, -0.80822297, 0.00054165, 0.80901445, 1.85687331, 2.75680191, 3.81986695, 5.00000000, 6.00000000,
+ 7.00000000, 8.00000000, -13.00000000, -12.00000000, -11.00000000, -10.00000000, -9.00000000, -8.00000000, -7.00000000, -6.00000000,
+-5.00000000, -3.88304817, -2.93396067, -1.86645989, -0.84825410, 0.00666207, 0.84853252, 1.88634684, 2.95282618, 3.89813287,
+ 4.89189079, 6.00000000, 7.00000000, 8.00000000, 9.00000000, 10.00000000, 11.00000000, -0.00344877, 1.00000000, -0.61413659,
+-0.02115630, 0.59438887, -0.60873054, 0.00844993, 0.62510557, -2.00000000, -0.75002947, 0.00120913, 0.66616051, -2.00000000,
+-0.72324691, 0.04760499, 0.70532533, 2.00000000, -3.00000000, -1.66577589, -0.78941380, -0.01909714, 0.74993685, 1.70945570,
+-1.64422308, -0.70992006, -0.02795108, 0.76990363, 1.79682243, 2.96233315, -1.71686461, -0.76572785, -0.00041846, 0.78174132,
+ 1.66217596, -3.00000000, -1.77033369, -0.79475091, 0.03709740, 0.80097076, 1.83947400, 2.85879773, -4.00000000, -3.16528651,
+-1.79564411, -0.90078981, 0.02403102, 0.86138856, 1.84207433, 2.74584048, -4.00000000, -2.91249347, -1.87804769, -0.87323549,
+ 0.08164382, 0.89037056, 1.82505263, 2.71336163, 4.00000000, -4.81262228, -3.87173565, -2.83424209, -1.87517938, -0.86199960,
+ 0.00268598, 0.89547657, 1.90713511, 2.85219071, 3.86417171, 4.80711781, 6.00000000, 7.00000000, -5.00000000, -3.82388480,
+-2.82875808, -1.90350457, -0.90795818, 0.03047007, 0.93676836, 1.88844957, 2.83269711, 3.76109686, 5.00000000, -9.00000000,
+-8.00000000, -6.88037957, -5.88776398, -4.91209139, -3.93902541, -2.90989221, -1.92281230, -0.98960535, -0.07440511, 0.94023957,
+ 1.91666262, 2.83340828, 3.83651295, 4.77839424, 6.12284019, 7.00000000, 8.00000000, 9.00000000, -12.00000000, -11.00000000,
+-10.00000000, -9.00000000, -8.00000000, -6.68554513, -5.97994708, -4.98789075, -3.91383581, -2.92952795, -1.91727195, -0.93148075,
+-0.00568870, 0.93515148, 1.94580068, 2.93838956, 3.92567644, 4.96573603, 5.95402763, 7.00000000, 8.00000000, 9.00000000,
+-11.00000000, -9.90096030, -8.97868124, -7.93663988, -6.98806055, -5.95937864, -4.93473664, -3.95454756, -2.96518446, -1.97711766,
+-0.98552111, -0.03317271, 0.95115775, 1.93785086, 2.96310779, 3.93322450, 5.01716212, 5.85909823, 6.89163669, 7.97492693,
+ 8.85698897, 9.79802946, 11.09373957, 12.00000000, -13.00000000, -12.00000000, -10.67579109, -9.95079100, -8.90576592, -7.93254656,
+-6.96112672, -5.96015798, -4.95493809, -3.98556269, -2.98182856, -1.98150255, -0.96551153, -0.00399791, 0.98644875, 1.98043830,
+ 2.97969033, 3.97728257, 4.95173541, 5.95649050, 6.96447378, 7.95591513, 9.07680954, 9.92093070, 10.76496555, 11.97525735,
+ 13.00000000, 14.00000000, -25.00000000, -24.00000000, -23.00000000, -22.00072357, -21.00000000, -20.00000000, -19.00000000, -18.20003462,
+-17.01648407, -15.78651996, -14.95660266, -13.99167850, -13.28722978, -11.85013840, -10.92025302, -9.87055810, -8.93841040, -7.95329867,
+-6.97819441, -6.01593394, -5.00905213, -3.99905285, -2.99171810, -1.99062796, -1.00112466, 0.00140492, 1.00701091, 2.02327185,
+ 3.00194633, 3.99188294, 5.00313145, 6.00448038, 6.98904951, 7.98158293, 8.98212774, 10.00363404, 10.98641678, 11.98034311,
+ 12.95176779, 13.95383703, 14.99084578, 15.98600642, 16.99406826, 17.98134623, 19.01793961, 19.86072639, 20.88465474, 21.99287082,
+ 22.81916620, 23.77946383, 0.00000234, 0.00000298, 0.00000048, 0.00002408, -0.00000165, -0.00001831, -0.00005703, -0.00000184,
+-1.00000000, 0.00001977, 1.00000000, -1.00000000, 0.00000010, 1.00000000, -1.00000000, -0.00001152, 1.00000000, -1.00000000,
+ 0.00000840, 1.00000000, -1.00000000, 0.00002353, 1.00000000, -0.75455603, -0.00001433, 1.00000000, -0.65859705, -0.00000703,
+ 0.62995860, -2.00000000, -0.72724652, -0.00033969, 0.61359174, 2.00000000, -2.00000000, -0.69510998, -0.00031410, 0.66467605,
+ 2.00000000, 3.00000000, -3.00000000, -2.00000000, -0.65738683, 0.00039019, 0.66554720, 1.91774106, 3.18089124, 0.00000070,
+ 0.00001152, -0.00000795, -0.00000058, -0.00003502, -0.00001508, -0.00004225, -0.00002165, -1.00000000, 0.00004391, 1.00000000,
+-1.00000000, 0.00001784, 1.00000000, -1.00000000, -0.00003678, 1.00000000, -0.68878314, -0.00013166, 0.60880149, -0.75291978,
+ 0.00006493, 1.00000000, -0.76757316, 0.00003057, 0.67140524, -0.61602267, -0.00014495, 0.63625803, 2.00000000, -2.00000000,
+-0.61253314, -0.00116483, 0.65071851, 2.00000000, -3.00000000, -1.71451667, -0.67799909, -0.00048294, 0.65846019, 2.00000000,
+-3.02497593, -1.83515395, -0.70317981, 0.00519701, 0.67780009, 1.84218153, 2.88846262, 4.00000000, 0.00001124, 0.00000588,
+-0.00000172, 0.00002835, 1.00000000, 0.00001012, -0.00008644, 1.00000000, -0.75115901, 0.00004347, 1.00000000, -1.00000000,
+ 0.00002800, 1.00000000, -1.00000000, -0.00006039, 1.00000000, -0.79763258, -0.00011907, 0.71713616, -0.76791870, -0.00007113,
+ 0.63583609, -0.62337806, 0.00012891, 0.62242094, -0.60837055, 0.00043216, 0.65515705, -0.63637782, -0.00019749, 0.60423967,
+ 2.00000000, -2.00000000, -0.65404827, -0.00089304, 0.64706660, 2.00000000, -1.86334076, -0.66410366, 0.00063219, 0.66968004,
+ 2.00000000, 3.00000000, 4.00000000, -4.00000000, -3.00000000, -1.79048834, -0.69451890, 0.00030677, 0.71009333, 1.70591343,
+ 3.00000000, 4.00000000, -4.00000000, -2.90176499, -1.78368781, -0.74425178, 0.00234068, 0.74847325, 1.78886822, 2.78478854,
+ 3.83608985, 4.95996151, 0.00002170, 0.00001281, 0.00002162, -1.00000000, -0.00007266, 1.00000000, -1.00000000, -0.00003250,
+-0.64088804, 0.00015239, 1.00000000, -0.58450370, -0.00008410, 0.60567186, -1.00000000, -0.00010752, 1.00000000, -0.58922508,
+-0.00017378, 0.60755779, -0.62797206, -0.00001016, 0.64432847, -0.58497934, -0.00001851, 0.59716791, -0.62642499, -0.00097386,
+ 0.63568558, 2.00000000, -2.00000000, -0.63236390, -0.00173361, 0.63142762, 1.75629192, -3.00000000, -2.00000000, -0.65596684,
+ 0.00209364, 0.65419742, 2.00000000, -3.00000000, -1.73856625, -0.67767521, -0.00119512, 0.68973603, 1.70985573, 3.00000000,
+-3.00000000, -1.81820220, -0.73974134, 0.00695869, 0.72216179, 1.75624461, 3.00000000, 4.00000000, -5.00000000, -4.00000000,
+-3.17718593, -1.76857567, -0.76822322, 0.00267400, 0.76414602, 1.84309221, 3.04940652, 4.00000000, -7.08189123, -6.00000000,
+-5.22882249, -3.96477958, -2.79653492, -1.81923435, -0.80050253, -0.01086663, 0.82708565, 1.85804900, 2.89996354, 3.76028554,
+ 4.80518081, 5.81738096, 7.00000000, 8.00000000, 9.08816091, -0.00002979, -0.00000333, -1.00000000, -0.00011532, 1.00000000,
+-0.70921122, -0.00005325, 0.68933188, -0.67581263, -0.00023107, 0.57868212, -0.58388312, -0.00020850, 0.60149012, -0.60912457,
+ 0.00001567, 0.60180554, -0.59130091, -0.00038863, 0.59908653, -2.00000000, -0.63697707, 0.00083913, 0.62040514, 2.00000000,
+-2.00000000, -0.63216238, -0.00081100, 0.64411071, 2.00000000, -1.76856259, -0.65266989, -0.00243486, 0.66888899, 2.00000000,
+-1.75427214, -0.71415385, -0.00226376, 0.71296778, 1.66182947, 3.00000000, -3.00000000, -1.72505821, -0.72920134, -0.00360424,
+ 0.73800767, 1.72848281, 3.00000000, -4.00000000, -2.95284408, -1.72025758, -0.76503859, 0.00418761, 0.75297139, 1.73959808,
+ 3.00000000, -5.00000000, -3.96232791, -2.74080544, -1.78897123, -0.80233505, -0.00002050, 0.79693417, 1.76182598, 2.78434458,
+ 3.85693287, 5.00000000, -6.00000000, -4.78439284, -3.83501790, -2.85203629, -1.84909573, -0.85382658, -0.00181019, 0.84735145,
+ 1.83676575, 2.83656843, 3.86722376, 4.79702431, 6.00000000, -9.00000000, -8.00000000, -7.00000000, -6.07957292, -4.84677515,
+-3.85093972, -2.88683139, -1.84596391, -0.88058034, -0.00008692, 0.87554746, 1.86933183, 2.84729990, 3.89029797, 4.87311773,
+ 5.90844023, 7.00000000, -11.00000000, -9.97745420, -8.90015761, -7.94187517, -6.86987726, -5.84795335, -4.86693435, -3.90601819,
+-2.91031804, -1.91620096, -0.90497055, 0.00659199, 0.90926869, 1.90980821, 2.91070850, 3.93685967, 4.85581177, 6.06727337,
+ 7.05801043, 8.00000000, 9.00000000, 10.00000000, 10.90825787, 12.00000000, 13.00000000, 14.00000000, -0.00008918, 1.00000000,
+-0.54405938, 0.00120348, 0.55781920, -0.59227786, -0.00349602, 0.59777231, -1.63717598, -0.69048065, 0.00999281, 0.65770558,
+ 2.00000000, -2.00000000, -0.71013571, 0.00454518, 0.66991065, -3.00000000, -1.73004867, -0.73743921, 0.01162454, 0.69964842,
+ 1.83319587, -1.81225491, -0.76806000, 0.00164742, 0.76780397, 1.67168896, -1.64564794, -0.79903361, -0.01522880, 0.84277926,
+ 1.68873752, -3.00000000, -1.72063244, -0.83687428, 0.00246724, 0.84618697, 1.79464483, 2.77447025, -3.77118426, -2.75025539,
+-1.82050448, -0.90373722, -0.00187780, 0.90102245, 1.85249394, 2.71364180, -2.71720889, -1.79466125, -0.89860801, -0.02725825,
+ 0.90877329, 1.90542096, 2.76847902, 3.71496428, -4.70257302, -3.90746659, -2.87078421, -1.88858709, -0.93608993, -0.02157425,
+ 0.95181182, 1.91155682, 2.83614575, 3.87820801, 4.72172277, -5.02764544, -3.80066801, -2.87484378, -1.90707477, -0.96326017,
+-0.01060091, 0.96558851, 1.92191548, 2.86970759, 3.85655474, 4.83135970, 5.76387469, -9.00000000, -8.00000000, -6.75261776,
+-5.86333393, -4.84846871, -3.91871758, -2.93827286, -1.93050320, -0.96359634, -0.00141931, 0.95926312, 1.92541870, 2.93009411,
+ 3.86699087, 4.82315929, 5.67815206, -8.76594345, -7.70350451, -6.91784020, -5.81539490, -4.92526872, -3.91513203, -2.92134949,
+-1.95465646, -0.97638102, -0.00742564, 0.96948714, 1.96401112, 2.95256722, 3.93146353, 4.90991357, 5.88139022, 6.88640588,
+ 7.82610489, 9.00000000, -10.97611369, -9.80036760, -8.91109518, -7.92809404, -6.93865353, -5.91965899, -4.92957669, -3.95206224,
+-2.97308718, -1.97778214, -0.98552568, -0.00063212, 0.98686014, 1.97511867, 2.97114218, 3.97854244, 4.96578513, 5.96457765,
+ 6.95180187, 7.95163483, 8.93760897, 9.87666900, 10.88024562, 11.96270158, 12.99519291, -15.00000000, -13.76826291, -12.97229116,
+-12.00334834, -10.95980884, -9.98190891, -8.93798503, -7.95621309, -6.96109479, -5.96056649, -4.95843419, -3.97688640, -2.98989576,
+-1.98533395, -0.99580972, 0.00694370, 0.99421120, 1.99033132, 2.98751217, 3.98549580, 4.96482394, 5.96623233, 6.93564626,
+ 7.93772467, 8.92015276, 9.88785129, 10.97606096, 11.79686057, -23.00000000, -22.00000000, -21.00000000, -20.00000000, -19.00000000,
+-17.73310977, -16.83574096, -15.90889480, -15.00437366, -13.95007272, -12.99296117, -11.98334751, -10.96970820, -9.97775151, -8.98193840,
+-7.98378966, -6.98887770, -5.99059477, -5.00228769, -3.99355850, -2.99947486, -1.99897483, -0.99375857, 0.00324880, 1.00215912,
+ 1.99277083, 3.00503747, 3.99390482, 4.98854283, 5.98753219, 6.98245347, 7.98089893, 8.95960522, 9.95663648, 11.00810285,
+ 12.01421617, 12.96208687, 13.99227766, 14.97230040, 15.95114804, 16.97347393, 17.97794884, 18.96777118, 19.94446034, 20.94799029,
+ 22.14740083, 22.84288347, 23.99212109, 25.00000000, 25.96562658};
+
+/* cdf tables for quantizer indices */
+const WebRtc_UWord16 WebRtcIsac_kQKltCdfGain[1212] = {
+ 0, 13, 301, 3730, 61784, 65167, 65489, 65535, 0, 17,
+ 142, 314, 929, 2466, 7678, 56450, 63463, 64740, 65204, 65426,
+ 65527, 65535, 0, 8, 100, 724, 6301, 60105, 65125, 65510,
+ 65531, 65535, 0, 13, 117, 368, 1068, 3010, 11928, 53603,
+ 61177, 63404, 64505, 65108, 65422, 65502, 65531, 65535, 0, 4,
+ 17, 96, 410, 1859, 12125, 54361, 64103, 65305, 65497, 65535,
+ 0, 4, 88, 230, 469, 950, 1746, 3228, 6092, 16592,
+ 44756, 56848, 61256, 63308, 64325, 64920, 65309, 65460, 65502, 65522,
+ 65535, 0, 88, 352, 1675, 6339, 20749, 46686, 59284, 63525,
+ 64949, 65359, 65502, 65527, 65535, 0, 13, 38, 63, 117,
+ 234, 381, 641, 929, 1407, 2043, 2809, 4032, 5753, 8792,
+ 14407, 24308, 38941, 48947, 55403, 59293, 61411, 62688, 63630, 64329,
+ 64840, 65188, 65376, 65472, 65506, 65527, 65531, 65535, 0, 8,
+ 29, 75, 222, 615, 1327, 2801, 5623, 9931, 16094, 24966,
+ 34419, 43458, 50676, 56186, 60055, 62500, 63936, 64765, 65225, 65435,
+ 65514, 65535, 0, 8, 13, 15, 17, 21, 33, 59,
+ 71, 92, 151, 243, 360, 456, 674, 934, 1223, 1583,
+ 1989, 2504, 3031, 3617, 4354, 5154, 6163, 7411, 8780, 10747,
+ 12874, 15591, 18974, 23027, 27436, 32020, 36948, 41830, 46205, 49797,
+ 53042, 56094, 58418, 60360, 61763, 62818, 63559, 64103, 64509, 64798,
+ 65045, 65162, 65288, 65363, 65447, 65506, 65522, 65531, 65533, 65535,
+ 0, 4, 6, 25, 38, 71, 138, 264, 519, 808,
+ 1227, 1825, 2516, 3408, 4279, 5560, 7092, 9197, 11420, 14108,
+ 16947, 20300, 23926, 27459, 31164, 34827, 38575, 42178, 45540, 48747,
+ 51444, 54090, 56426, 58460, 60080, 61595, 62734, 63668, 64275, 64673,
+ 64936, 65112, 65217, 65334, 65426, 65464, 65477, 65489, 65518, 65527,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 8, 10, 12,
+ 14, 16, 21, 33, 50, 71, 84, 92, 105, 138,
+ 180, 255, 318, 377, 435, 473, 511, 590, 682, 758,
+ 913, 1097, 1256, 1449, 1671, 1884, 2169, 2445, 2772, 3157,
+ 3563, 3944, 4375, 4848, 5334, 5820, 6448, 7101, 7716, 8378,
+ 9102, 9956, 10752, 11648, 12707, 13670, 14758, 15910, 17187, 18472,
+ 19627, 20649, 21951, 23169, 24283, 25552, 26862, 28227, 29391, 30764,
+ 31882, 33213, 34432, 35600, 36910, 38116, 39464, 40729, 41872, 43144,
+ 44371, 45514, 46762, 47813, 48968, 50069, 51032, 51974, 52908, 53737,
+ 54603, 55445, 56282, 56990, 57572, 58191, 58840, 59410, 59887, 60264,
+ 60607, 60946, 61269, 61516, 61771, 61960, 62198, 62408, 62558, 62776,
+ 62985, 63207, 63408, 63546, 63739, 63906, 64070, 64237, 64371, 64551,
+ 64677, 64836, 64999, 65095, 65213, 65284, 65338, 65380, 65426, 65447,
+ 65472, 65485, 65487, 65489, 65502, 65510, 65512, 65514, 65516, 65518,
+ 65522, 65531, 65533, 65535, 0, 2, 4, 6, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 222, 65321,
+ 65513, 65528, 65531, 65533, 65535, 0, 2, 4, 50, 65476,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 12,
+ 38, 544, 64936, 65509, 65523, 65525, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 1055, 64508, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 10, 12, 123,
+ 3956, 62999, 65372, 65495, 65515, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 12, 53, 4707, 59445,
+ 65467, 65525, 65527, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 38, 40, 50, 67,
+ 96, 234, 929, 14345, 55750, 64866, 65389, 65462, 65514, 65517,
+ 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 15, 35, 91, 377, 1946,
+ 13618, 52565, 63714, 65184, 65465, 65520, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52,
+ 54, 82, 149, 362, 751, 1701, 4239, 12893, 38627, 55072,
+ 60875, 63071, 64158, 64702, 65096, 65283, 65412, 65473, 65494, 65505,
+ 65508, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 15, 23, 53, 143, 260, 418, 698,
+ 988, 1353, 1812, 2411, 3144, 4015, 5143, 6401, 7611, 8999,
+ 10653, 12512, 14636, 16865, 19404, 22154, 24798, 27521, 30326, 33102,
+ 35790, 38603, 41415, 43968, 46771, 49435, 52152, 54715, 57143, 59481,
+ 61178, 62507, 63603, 64489, 64997, 65257, 65427, 65473, 65503, 65520,
+ 65529, 65531, 65533, 65535, 0, 3, 6, 9, 26, 32,
+ 44, 46, 64, 94, 111, 164, 205, 254, 327, 409,
+ 506, 608, 733, 885, 1093, 1292, 1482, 1742, 1993, 2329,
+ 2615, 3029, 3374, 3798, 4257, 4870, 5405, 5992, 6618, 7225,
+ 7816, 8418, 9051, 9761, 10532, 11380, 12113, 13010, 13788, 14594,
+ 15455, 16361, 17182, 18088, 18997, 20046, 20951, 21968, 22947, 24124,
+ 25296, 26547, 27712, 28775, 29807, 30835, 31709, 32469, 33201, 34014,
+ 34876, 35773, 36696, 37620, 38558, 39547, 40406, 41277, 42367, 43290,
+ 44445, 45443, 46510, 47684, 48973, 50157, 51187, 52242, 53209, 54083,
+ 55006, 55871, 56618, 57293, 57965, 58556, 59222, 59722, 60180, 60554,
+ 60902, 61250, 61554, 61837, 62100, 62372, 62631, 62856, 63078, 63324,
+ 63557, 63768, 63961, 64089, 64235, 64352, 64501, 64633, 64770, 64887,
+ 65001, 65059, 65121, 65188, 65246, 65302, 65346, 65390, 65428, 65463,
+ 65477, 65506, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529,
+ 65531, 65533, 65535, 0, 2, 4, 109, 65332, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 25, 1817, 63874, 65511,
+ 65527, 65529, 65531, 65533, 65535, 0, 2, 4, 907, 65014,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8, 10,
+ 12, 132, 2743, 62708, 65430, 65525, 65527, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 6, 8, 35, 3743, 61666, 65485,
+ 65531, 65533, 65535, 0, 2, 4, 6, 8, 10, 23,
+ 109, 683, 6905, 58417, 64911, 65398, 65497, 65518, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 6, 53, 510,
+ 10209, 55212, 64573, 65441, 65522, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 32, 90, 266, 1037, 3349, 14468, 50488, 62394, 64685,
+ 65341, 65480, 65514, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535, 0, 2, 4, 6, 9, 16, 37, 106,
+ 296, 748, 1868, 5733, 18897, 45553, 60165, 63949, 64926, 65314,
+ 65441, 65508, 65524, 65529, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 83, 175, 344, 667, 1293, 2337, 4357,
+ 8033, 14988, 28600, 43244, 52011, 57042, 59980, 61779, 63065, 63869,
+ 64390, 64753, 64988, 65164, 65326, 65422, 65462, 65492, 65506, 65522,
+ 65524, 65526, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 14, 16, 25, 39, 48, 55, 62, 65,
+ 85, 106, 139, 169, 194, 252, 323, 485, 688, 1074,
+ 1600, 2544, 3863, 5733, 8303, 11397, 15529, 20273, 25734, 31455,
+ 36853, 41891, 46410, 50306, 53702, 56503, 58673, 60479, 61880, 62989,
+ 63748, 64404, 64852, 65124, 65309, 65424, 65480, 65524, 65528, 65533,
+ 65535, 0, 2, 4, 6, 8, 10, 12, 14, 21,
+ 23, 25, 27, 29, 31, 39, 41, 43, 48, 60,
+ 72, 79, 106, 136, 166, 187, 224, 252, 323, 381,
+ 427, 478, 568, 660, 783, 912, 1046, 1175, 1365, 1567,
+ 1768, 2024, 2347, 2659, 3049, 3529, 4033, 4623, 5281, 5925,
+ 6726, 7526, 8417, 9468, 10783, 12141, 13571, 15222, 16916, 18659,
+ 20350, 22020, 23725, 25497, 27201, 29026, 30867, 32632, 34323, 36062,
+ 37829, 39466, 41144, 42654, 43981, 45343, 46579, 47759, 49013, 50171,
+ 51249, 52283, 53245, 54148, 54938, 55669, 56421, 57109, 57791, 58464,
+ 59092, 59674, 60105, 60653, 61083, 61407, 61757, 62095, 62388, 62649,
+ 62873, 63157, 63358, 63540, 63725, 63884, 64046, 64155, 64278, 64426,
+ 64548, 64654, 64806, 64906, 64994, 65077, 65137, 65215, 65277, 65324,
+ 65354, 65409, 65437, 65455, 65462, 65490, 65495, 65499, 65508, 65511,
+ 65513, 65515, 65517, 65519, 65521, 65523, 65525, 65527, 65529, 65531,
+ 65533, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQKltCdfShape[2059] = {
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4,
+ 65535, 0, 8, 65514, 65535, 0, 29, 65481, 65535, 0,
+ 121, 65439, 65535, 0, 239, 65284, 65535, 0, 8, 779,
+ 64999, 65527, 65535, 0, 8, 888, 64693, 65522, 65535, 0,
+ 29, 2604, 62843, 65497, 65531, 65535, 0, 25, 176, 4576,
+ 61164, 65275, 65527, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 4, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 4, 65535, 0, 33, 65502, 65535,
+ 0, 54, 65481, 65535, 0, 251, 65309, 65535, 0, 611,
+ 65074, 65535, 0, 1273, 64292, 65527, 65535, 0, 4, 1809,
+ 63940, 65518, 65535, 0, 88, 4392, 60603, 65426, 65531, 65535,
+ 0, 25, 419, 7046, 57756, 64961, 65514, 65531, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 4, 65531,
+ 65535, 0, 65535, 0, 8, 65531, 65535, 0, 4, 65527,
+ 65535, 0, 17, 65510, 65535, 0, 42, 65481, 65535, 0,
+ 197, 65342, 65531, 65535, 0, 385, 65154, 65535, 0, 1005,
+ 64522, 65535, 0, 8, 1985, 63469, 65533, 65535, 0, 38,
+ 3119, 61884, 65514, 65535, 0, 4, 6, 67, 4961, 60804,
+ 65472, 65535, 0, 17, 565, 9182, 56538, 65087, 65514, 65535,
+ 0, 8, 63, 327, 2118, 14490, 52774, 63839, 65376, 65522,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 17, 65522, 65535, 0, 59, 65489, 65535, 0, 50, 65522,
+ 65535, 0, 54, 65489, 65535, 0, 310, 65179, 65535, 0,
+ 615, 64836, 65535, 0, 4, 1503, 63965, 65535, 0, 2780,
+ 63383, 65535, 0, 21, 3919, 61051, 65527, 65535, 0, 84,
+ 6674, 59929, 65435, 65535, 0, 4, 255, 7976, 55784, 65150,
+ 65518, 65531, 65535, 0, 4, 8, 582, 10726, 53465, 64949,
+ 65518, 65535, 0, 29, 339, 3006, 17555, 49517, 62956, 65200,
+ 65497, 65531, 65535, 0, 2, 33, 138, 565, 2324, 7670,
+ 22089, 45966, 58949, 63479, 64966, 65380, 65518, 65535, 0, 65535,
+ 0, 65535, 0, 2, 65533, 65535, 0, 46, 65514, 65535,
+ 0, 414, 65091, 65535, 0, 540, 64911, 65535, 0, 419,
+ 65162, 65535, 0, 976, 64790, 65535, 0, 2977, 62495, 65531,
+ 65535, 0, 4, 3852, 61034, 65527, 65535, 0, 4, 29,
+ 6021, 60243, 65468, 65535, 0, 84, 6711, 58066, 65418, 65535,
+ 0, 13, 281, 9550, 54917, 65125, 65506, 65535, 0, 2,
+ 63, 984, 12108, 52644, 64342, 65435, 65527, 65535, 0, 29,
+ 251, 2014, 14871, 47553, 62881, 65229, 65518, 65535, 0, 13,
+ 142, 749, 4220, 18497, 45200, 60913, 64823, 65426, 65527, 65535,
+ 0, 13, 71, 264, 1176, 3789, 10500, 24480, 43488, 56324,
+ 62315, 64493, 65242, 65464, 65514, 65522, 65531, 65535, 0, 4,
+ 13, 38, 109, 205, 448, 850, 1708, 3429, 6276, 11371,
+ 19221, 29734, 40955, 49391, 55411, 59460, 62102, 63793, 64656, 65150,
+ 65401, 65485, 65522, 65531, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 1160, 65476, 65535, 0, 2, 6640, 64763, 65533,
+ 65535, 0, 2, 38, 9923, 61009, 65527, 65535, 0, 2,
+ 4949, 63092, 65533, 65535, 0, 2, 3090, 63398, 65533, 65535,
+ 0, 2, 2520, 58744, 65510, 65535, 0, 2, 13, 544,
+ 8784, 51403, 65148, 65533, 65535, 0, 2, 25, 1017, 10412,
+ 43550, 63651, 65489, 65527, 65535, 0, 2, 4, 29, 783,
+ 13377, 52462, 64524, 65495, 65533, 65535, 0, 2, 4, 6,
+ 100, 1817, 18451, 52590, 63559, 65376, 65531, 65535, 0, 2,
+ 4, 6, 46, 385, 2562, 11225, 37416, 60488, 65026, 65487,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 12,
+ 42, 222, 971, 5221, 19811, 45048, 60312, 64486, 65294, 65474,
+ 65525, 65529, 65533, 65535, 0, 2, 4, 8, 71, 167,
+ 666, 2533, 7875, 19622, 38082, 54359, 62108, 64633, 65290, 65495,
+ 65529, 65533, 65535, 0, 2, 4, 6, 8, 10, 13,
+ 109, 586, 1930, 4949, 11600, 22641, 36125, 48312, 56899, 61495,
+ 63927, 64932, 65389, 65489, 65518, 65531, 65533, 65535, 0, 4,
+ 6, 8, 67, 209, 712, 1838, 4195, 8432, 14432, 22834,
+ 31723, 40523, 48139, 53929, 57865, 60657, 62403, 63584, 64363, 64907,
+ 65167, 65372, 65472, 65514, 65535, 0, 2, 4, 13, 25,
+ 42, 46, 50, 75, 113, 147, 281, 448, 657, 909,
+ 1185, 1591, 1976, 2600, 3676, 5317, 7398, 9914, 12941, 16169,
+ 19477, 22885, 26464, 29851, 33360, 37228, 41139, 44802, 48654, 52058,
+ 55181, 57676, 59581, 61022, 62190, 63107, 63676, 64199, 64547, 64924,
+ 65158, 65313, 65430, 65481, 65518, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65533, 65535, 0, 2, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 2, 4, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 4, 65531, 65533, 65535, 0, 2, 4, 65531,
+ 65533, 65535, 0, 2, 4, 6, 65524, 65533, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0, 65533,
+ 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0,
+ 2, 65533, 65535, 0, 2, 4, 65532, 65535, 0, 6,
+ 65523, 65535, 0, 2, 15, 65530, 65533, 65535, 0, 2,
+ 35, 65493, 65531, 65533, 65535, 0, 2, 4, 158, 65382,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 2, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 9, 65512, 65535, 0, 2,
+ 12, 65529, 65535, 0, 2, 73, 65434, 65533, 65535, 0,
+ 2, 240, 65343, 65533, 65535, 0, 2, 476, 65017, 65531,
+ 65533, 65535, 0, 2, 4, 1046, 64686, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 1870, 63898, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65532, 65535, 0, 6, 65533, 65535, 0, 6, 65523, 65535,
+ 0, 2, 65532, 65535, 0, 137, 65439, 65535, 0, 576,
+ 64899, 65533, 65535, 0, 2, 289, 65299, 65533, 65535, 0,
+ 2, 4, 6, 880, 64134, 65531, 65533, 65535, 0, 2,
+ 4, 1853, 63347, 65533, 65535, 0, 2, 6, 2516, 61762,
+ 65529, 65531, 65533, 65535, 0, 2, 4, 9, 3980, 61380,
+ 65503, 65529, 65531, 65533, 65535, 0, 2, 4, 6, 8,
+ 10, 12, 61, 6393, 59859, 65466, 65527, 65529, 65531, 65533,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2, 65532,
+ 65535, 0, 3, 65529, 65535, 0, 2, 65529, 65535, 0,
+ 61, 65453, 65535, 0, 234, 65313, 65535, 0, 503, 65138,
+ 65535, 0, 155, 65402, 65533, 65535, 0, 2, 1058, 64554,
+ 65533, 65535, 0, 2, 4, 3138, 62109, 65531, 65533, 65535,
+ 0, 2, 4, 2031, 63339, 65531, 65533, 65535, 0, 2,
+ 4, 6, 9, 4155, 60778, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 41, 6189, 59269, 65490, 65531, 65533, 65535,
+ 0, 2, 4, 6, 210, 8789, 57043, 65400, 65528, 65531,
+ 65533, 65535, 0, 2, 4, 6, 8, 26, 453, 10086,
+ 55499, 64948, 65483, 65524, 65527, 65529, 65531, 65533, 65535, 0,
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 114, 1014, 11202, 52670, 64226, 65356, 65503, 65514, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 15,
+ 65301, 65535, 0, 152, 64807, 65535, 0, 2, 3328, 63308,
+ 65535, 0, 2, 4050, 59730, 65533, 65535, 0, 2, 164,
+ 10564, 61894, 65529, 65535, 0, 15, 6712, 59831, 65076, 65532,
+ 65535, 0, 32, 7712, 57449, 65459, 65535, 0, 2, 210,
+ 7849, 53110, 65021, 65523, 65535, 0, 2, 12, 1081, 13883,
+ 48262, 62870, 65477, 65535, 0, 2, 88, 847, 6145, 37852,
+ 62012, 65454, 65533, 65535, 0, 9, 47, 207, 1823, 14522,
+ 45521, 61069, 64891, 65481, 65528, 65531, 65533, 65535, 0, 2,
+ 9, 488, 2881, 12758, 38703, 58412, 64420, 65410, 65533, 65535,
+ 0, 2, 4, 6, 61, 333, 1891, 6486, 19720, 43188,
+ 57547, 62472, 64796, 65421, 65497, 65523, 65529, 65531, 65533, 65535,
+ 0, 2, 4, 6, 8, 10, 12, 29, 117, 447,
+ 1528, 6138, 21242, 43133, 56495, 62432, 64746, 65362, 65500, 65529,
+ 65531, 65533, 65535, 0, 2, 18, 105, 301, 760, 1490,
+ 3472, 7568, 15002, 26424, 40330, 53029, 60048, 62964, 64274, 64890,
+ 65337, 65445, 65489, 65513, 65527, 65530, 65533, 65535, 0, 2,
+ 4, 6, 41, 102, 409, 853, 2031, 4316, 7302, 11328,
+ 16869, 24825, 34926, 43481, 50877, 56126, 59874, 62103, 63281, 63857,
+ 64166, 64675, 65382, 65522, 65531, 65533, 65535, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 29, 38, 53,
+ 58, 96, 181, 503, 1183, 2849, 5590, 8600, 11379, 13942,
+ 16478, 19453, 22638, 26039, 29411, 32921, 37596, 41433, 44998, 48560,
+ 51979, 55106, 57666, 59892, 61485, 62616, 63484, 64018, 64375, 64685,
+ 64924, 65076, 65278, 65395, 65471, 65509, 65529, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535,
+ 0, 65535, 0, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533, 65535,
+ 0, 2, 65533, 65535, 0, 2, 65533, 65535, 0, 7,
+ 65519, 65535, 0, 2, 14, 65491, 65533, 65535, 0, 2,
+ 81, 65427, 65531, 65533, 65535, 0, 2, 4, 312, 65293,
+ 65528, 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 65535, 0, 65535, 0, 65535, 0, 65535, 0, 65535, 0,
+ 2, 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65533,
+ 65535, 0, 5, 65523, 65535, 0, 2, 65533, 65535, 0,
+ 7, 65526, 65535, 0, 46, 65464, 65533, 65535, 0, 2,
+ 120, 65309, 65533, 65535, 0, 2, 5, 362, 65097, 65533,
+ 65535, 0, 2, 18, 1164, 64785, 65528, 65531, 65533, 65535,
+ 0, 65535, 0, 65535, 0, 65535, 0, 65533, 65535, 0,
+ 65535, 0, 65533, 65535, 0, 2, 65533, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65533, 65535, 0, 2, 65530, 65535,
+ 0, 2, 65523, 65535, 0, 69, 65477, 65535, 0, 141,
+ 65459, 65535, 0, 194, 65325, 65533, 65535, 0, 2, 543,
+ 64912, 65533, 65535, 0, 5, 1270, 64301, 65529, 65531, 65533,
+ 65535, 0, 2, 4, 12, 2055, 63538, 65508, 65531, 65533,
+ 65535, 0, 2, 7, 102, 3775, 61970, 65429, 65526, 65528,
+ 65533, 65535, 0, 65535, 0, 65535, 0, 65535, 0, 2,
+ 65533, 65535, 0, 2, 65535, 0, 9, 65533, 65535, 0,
+ 25, 65512, 65535, 0, 2, 65533, 65535, 0, 44, 65480,
+ 65535, 0, 48, 65475, 65535, 0, 162, 65373, 65535, 0,
+ 637, 64806, 65533, 65535, 0, 2, 935, 64445, 65533, 65535,
+ 0, 2, 4, 1662, 64083, 65533, 65535, 0, 2, 12,
+ 3036, 62469, 65521, 65533, 65535, 0, 2, 120, 5405, 60468,
+ 65469, 65531, 65533, 65535, 0, 2, 4, 18, 254, 6663,
+ 58999, 65272, 65528, 65533, 65535, 0, 2, 4, 9, 12,
+ 67, 591, 8981, 56781, 64564, 65365, 65508, 65524, 65526, 65529,
+ 65531, 65533, 65535, 0, 65535, 0, 65535, 0, 2, 65533,
+ 65535, 0, 9, 65526, 65535, 0, 14, 65503, 65535, 0,
+ 127, 65390, 65535, 0, 517, 64990, 65535, 0, 178, 65330,
+ 65535, 0, 2, 1055, 64533, 65533, 65535, 0, 2, 1558,
+ 63942, 65533, 65535, 0, 2, 2205, 63173, 65533, 65535, 0,
+ 25, 4493, 60862, 65505, 65533, 65535, 0, 2, 48, 5890,
+ 59442, 65482, 65533, 65535, 0, 2, 4, 127, 7532, 58191,
+ 65394, 65533, 65535, 0, 2, 5, 32, 550, 10388, 54924,
+ 65046, 65510, 65531, 65533, 65535, 0, 2, 4, 30, 150,
+ 1685, 14340, 51375, 63619, 65288, 65503, 65528, 65533, 65535, 0,
+ 2, 4, 6, 8, 28, 97, 473, 2692, 15407, 50020,
+ 62880, 65064, 65445, 65508, 65531, 65533, 65535, 0, 2, 4,
+ 12, 32, 79, 150, 372, 907, 2184, 5868, 18207, 45431,
+ 59856, 64031, 65096, 65401, 65481, 65507, 65521, 65523, 65525, 65527,
+ 65529, 65531, 65533, 65535, 0, 65533, 65535, 0, 182, 65491,
+ 65535, 0, 877, 64286, 65535, 0, 9, 2708, 63612, 65533,
+ 65535, 0, 2, 6038, 59532, 65535, 0, 2, 92, 5500,
+ 60539, 65533, 65535, 0, 268, 8908, 56512, 65385, 65535, 0,
+ 129, 13110, 52742, 65036, 65535, 0, 2, 806, 14003, 51929,
+ 64732, 65523, 65535, 0, 7, 92, 2667, 18159, 47678, 62610,
+ 65355, 65535, 0, 32, 1836, 19676, 48237, 61677, 64960, 65526,
+ 65535, 0, 21, 159, 967, 5668, 22782, 44709, 58317, 64020,
+ 65406, 65528, 65535, 0, 7, 162, 1838, 8328, 23929, 43014,
+ 56394, 63374, 65216, 65484, 65521, 65535, 0, 2, 4, 6,
+ 28, 268, 1120, 3613, 10688, 24185, 40989, 54917, 61684, 64510,
+ 65403, 65530, 65535, 0, 2, 16, 44, 139, 492, 1739,
+ 5313, 13558, 26766, 41566, 52446, 58937, 62815, 64480, 65201, 65454,
+ 65524, 65533, 65535, 0, 7, 25, 76, 263, 612, 1466,
+ 3325, 6832, 12366, 20152, 29466, 39255, 47360, 53506, 57740, 60726,
+ 62845, 64131, 64882, 65260, 65459, 65521, 65528, 65530, 65535, 0,
+ 2, 4, 14, 48, 136, 312, 653, 1240, 2369, 4327,
+ 7028, 10759, 15449, 21235, 28027, 35386, 42938, 49562, 54990, 59119,
+ 62086, 63916, 64863, 65249, 65445, 65493, 65523, 65535, 0, 2,
+ 4, 6, 8, 10, 12, 21, 83, 208, 409, 723,
+ 1152, 1868, 2951, 4463, 6460, 8979, 11831, 15195, 18863, 22657,
+ 26762, 30881, 34963, 39098, 43054, 47069, 50620, 53871, 56821, 59386,
+ 61340, 62670, 63512, 64023, 64429, 64750, 64944, 65126, 65279, 65366,
+ 65413, 65445, 65473, 65505, 65510, 65521, 65528, 65530, 65535};
+
+/* pointers to cdf tables for quantizer indices */
+const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrGain[3][12] = {
+{WebRtcIsac_kQKltCdfGain +0 +0, WebRtcIsac_kQKltCdfGain +0 +8, WebRtcIsac_kQKltCdfGain +0 +22, WebRtcIsac_kQKltCdfGain +0 +32, WebRtcIsac_kQKltCdfGain +0 +48, WebRtcIsac_kQKltCdfGain +0 +60, WebRtcIsac_kQKltCdfGain +0 +81, WebRtcIsac_kQKltCdfGain +0 +95, WebRtcIsac_kQKltCdfGain +0 +128, WebRtcIsac_kQKltCdfGain +0 +152,
+WebRtcIsac_kQKltCdfGain +0 +210, WebRtcIsac_kQKltCdfGain +0 +264},
+{WebRtcIsac_kQKltCdfGain +404 +0, WebRtcIsac_kQKltCdfGain +404 +8, WebRtcIsac_kQKltCdfGain +404 +21, WebRtcIsac_kQKltCdfGain +404 +30, WebRtcIsac_kQKltCdfGain +404 +46, WebRtcIsac_kQKltCdfGain +404 +58, WebRtcIsac_kQKltCdfGain +404 +79, WebRtcIsac_kQKltCdfGain +404 +93, WebRtcIsac_kQKltCdfGain +404 +125, WebRtcIsac_kQKltCdfGain +404 +149,
+WebRtcIsac_kQKltCdfGain +404 +207, WebRtcIsac_kQKltCdfGain +404 +260},
+{WebRtcIsac_kQKltCdfGain +803 +0, WebRtcIsac_kQKltCdfGain +803 +8, WebRtcIsac_kQKltCdfGain +803 +22, WebRtcIsac_kQKltCdfGain +803 +31, WebRtcIsac_kQKltCdfGain +803 +48, WebRtcIsac_kQKltCdfGain +803 +60, WebRtcIsac_kQKltCdfGain +803 +81, WebRtcIsac_kQKltCdfGain +803 +96, WebRtcIsac_kQKltCdfGain +803 +129, WebRtcIsac_kQKltCdfGain +803 +154,
+WebRtcIsac_kQKltCdfGain +803 +212, WebRtcIsac_kQKltCdfGain +803 +268}};
+
+const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrShape[3][108] = {
+{WebRtcIsac_kQKltCdfShape +0 +0, WebRtcIsac_kQKltCdfShape +0 +2, WebRtcIsac_kQKltCdfShape +0 +4, WebRtcIsac_kQKltCdfShape +0 +6, WebRtcIsac_kQKltCdfShape +0 +8, WebRtcIsac_kQKltCdfShape +0 +10, WebRtcIsac_kQKltCdfShape +0 +12, WebRtcIsac_kQKltCdfShape +0 +14, WebRtcIsac_kQKltCdfShape +0 +16, WebRtcIsac_kQKltCdfShape +0 +18,
+WebRtcIsac_kQKltCdfShape +0 +21, WebRtcIsac_kQKltCdfShape +0 +25, WebRtcIsac_kQKltCdfShape +0 +29, WebRtcIsac_kQKltCdfShape +0 +33, WebRtcIsac_kQKltCdfShape +0 +37, WebRtcIsac_kQKltCdfShape +0 +43, WebRtcIsac_kQKltCdfShape +0 +49, WebRtcIsac_kQKltCdfShape +0 +56, WebRtcIsac_kQKltCdfShape +0 +64, WebRtcIsac_kQKltCdfShape +0 +66,
+WebRtcIsac_kQKltCdfShape +0 +68, WebRtcIsac_kQKltCdfShape +0 +70, WebRtcIsac_kQKltCdfShape +0 +72, WebRtcIsac_kQKltCdfShape +0 +75, WebRtcIsac_kQKltCdfShape +0 +77, WebRtcIsac_kQKltCdfShape +0 +79, WebRtcIsac_kQKltCdfShape +0 +81, WebRtcIsac_kQKltCdfShape +0 +83, WebRtcIsac_kQKltCdfShape +0 +86, WebRtcIsac_kQKltCdfShape +0 +90,
+WebRtcIsac_kQKltCdfShape +0 +94, WebRtcIsac_kQKltCdfShape +0 +98, WebRtcIsac_kQKltCdfShape +0 +102, WebRtcIsac_kQKltCdfShape +0 +107, WebRtcIsac_kQKltCdfShape +0 +113, WebRtcIsac_kQKltCdfShape +0 +120, WebRtcIsac_kQKltCdfShape +0 +129, WebRtcIsac_kQKltCdfShape +0 +131, WebRtcIsac_kQKltCdfShape +0 +133, WebRtcIsac_kQKltCdfShape +0 +135,
+WebRtcIsac_kQKltCdfShape +0 +137, WebRtcIsac_kQKltCdfShape +0 +141, WebRtcIsac_kQKltCdfShape +0 +143, WebRtcIsac_kQKltCdfShape +0 +147, WebRtcIsac_kQKltCdfShape +0 +151, WebRtcIsac_kQKltCdfShape +0 +155, WebRtcIsac_kQKltCdfShape +0 +159, WebRtcIsac_kQKltCdfShape +0 +164, WebRtcIsac_kQKltCdfShape +0 +168, WebRtcIsac_kQKltCdfShape +0 +172,
+WebRtcIsac_kQKltCdfShape +0 +178, WebRtcIsac_kQKltCdfShape +0 +184, WebRtcIsac_kQKltCdfShape +0 +192, WebRtcIsac_kQKltCdfShape +0 +200, WebRtcIsac_kQKltCdfShape +0 +211, WebRtcIsac_kQKltCdfShape +0 +213, WebRtcIsac_kQKltCdfShape +0 +215, WebRtcIsac_kQKltCdfShape +0 +217, WebRtcIsac_kQKltCdfShape +0 +219, WebRtcIsac_kQKltCdfShape +0 +223,
+WebRtcIsac_kQKltCdfShape +0 +227, WebRtcIsac_kQKltCdfShape +0 +231, WebRtcIsac_kQKltCdfShape +0 +235, WebRtcIsac_kQKltCdfShape +0 +239, WebRtcIsac_kQKltCdfShape +0 +243, WebRtcIsac_kQKltCdfShape +0 +248, WebRtcIsac_kQKltCdfShape +0 +252, WebRtcIsac_kQKltCdfShape +0 +258, WebRtcIsac_kQKltCdfShape +0 +264, WebRtcIsac_kQKltCdfShape +0 +273,
+WebRtcIsac_kQKltCdfShape +0 +282, WebRtcIsac_kQKltCdfShape +0 +293, WebRtcIsac_kQKltCdfShape +0 +308, WebRtcIsac_kQKltCdfShape +0 +310, WebRtcIsac_kQKltCdfShape +0 +312, WebRtcIsac_kQKltCdfShape +0 +316, WebRtcIsac_kQKltCdfShape +0 +320, WebRtcIsac_kQKltCdfShape +0 +324, WebRtcIsac_kQKltCdfShape +0 +328, WebRtcIsac_kQKltCdfShape +0 +332,
+WebRtcIsac_kQKltCdfShape +0 +336, WebRtcIsac_kQKltCdfShape +0 +341, WebRtcIsac_kQKltCdfShape +0 +347, WebRtcIsac_kQKltCdfShape +0 +354, WebRtcIsac_kQKltCdfShape +0 +360, WebRtcIsac_kQKltCdfShape +0 +368, WebRtcIsac_kQKltCdfShape +0 +378, WebRtcIsac_kQKltCdfShape +0 +388, WebRtcIsac_kQKltCdfShape +0 +400, WebRtcIsac_kQKltCdfShape +0 +418,
+WebRtcIsac_kQKltCdfShape +0 +445, WebRtcIsac_kQKltCdfShape +0 +447, WebRtcIsac_kQKltCdfShape +0 +451, WebRtcIsac_kQKltCdfShape +0 +455, WebRtcIsac_kQKltCdfShape +0 +461, WebRtcIsac_kQKltCdfShape +0 +468, WebRtcIsac_kQKltCdfShape +0 +474, WebRtcIsac_kQKltCdfShape +0 +480, WebRtcIsac_kQKltCdfShape +0 +486, WebRtcIsac_kQKltCdfShape +0 +495,
+WebRtcIsac_kQKltCdfShape +0 +505, WebRtcIsac_kQKltCdfShape +0 +516, WebRtcIsac_kQKltCdfShape +0 +528, WebRtcIsac_kQKltCdfShape +0 +543, WebRtcIsac_kQKltCdfShape +0 +564, WebRtcIsac_kQKltCdfShape +0 +583, WebRtcIsac_kQKltCdfShape +0 +608, WebRtcIsac_kQKltCdfShape +0 +635},
+{WebRtcIsac_kQKltCdfShape +686 +0, WebRtcIsac_kQKltCdfShape +686 +2, WebRtcIsac_kQKltCdfShape +686 +4, WebRtcIsac_kQKltCdfShape +686 +6, WebRtcIsac_kQKltCdfShape +686 +8, WebRtcIsac_kQKltCdfShape +686 +11, WebRtcIsac_kQKltCdfShape +686 +13, WebRtcIsac_kQKltCdfShape +686 +15, WebRtcIsac_kQKltCdfShape +686 +17, WebRtcIsac_kQKltCdfShape +686 +20,
+WebRtcIsac_kQKltCdfShape +686 +23, WebRtcIsac_kQKltCdfShape +686 +27, WebRtcIsac_kQKltCdfShape +686 +31, WebRtcIsac_kQKltCdfShape +686 +35, WebRtcIsac_kQKltCdfShape +686 +40, WebRtcIsac_kQKltCdfShape +686 +44, WebRtcIsac_kQKltCdfShape +686 +50, WebRtcIsac_kQKltCdfShape +686 +56, WebRtcIsac_kQKltCdfShape +686 +63, WebRtcIsac_kQKltCdfShape +686 +65,
+WebRtcIsac_kQKltCdfShape +686 +67, WebRtcIsac_kQKltCdfShape +686 +69, WebRtcIsac_kQKltCdfShape +686 +71, WebRtcIsac_kQKltCdfShape +686 +73, WebRtcIsac_kQKltCdfShape +686 +75, WebRtcIsac_kQKltCdfShape +686 +77, WebRtcIsac_kQKltCdfShape +686 +79, WebRtcIsac_kQKltCdfShape +686 +82, WebRtcIsac_kQKltCdfShape +686 +85, WebRtcIsac_kQKltCdfShape +686 +89,
+WebRtcIsac_kQKltCdfShape +686 +93, WebRtcIsac_kQKltCdfShape +686 +97, WebRtcIsac_kQKltCdfShape +686 +102, WebRtcIsac_kQKltCdfShape +686 +106, WebRtcIsac_kQKltCdfShape +686 +112, WebRtcIsac_kQKltCdfShape +686 +119, WebRtcIsac_kQKltCdfShape +686 +127, WebRtcIsac_kQKltCdfShape +686 +129, WebRtcIsac_kQKltCdfShape +686 +131, WebRtcIsac_kQKltCdfShape +686 +133,
+WebRtcIsac_kQKltCdfShape +686 +135, WebRtcIsac_kQKltCdfShape +686 +137, WebRtcIsac_kQKltCdfShape +686 +139, WebRtcIsac_kQKltCdfShape +686 +142, WebRtcIsac_kQKltCdfShape +686 +146, WebRtcIsac_kQKltCdfShape +686 +150, WebRtcIsac_kQKltCdfShape +686 +154, WebRtcIsac_kQKltCdfShape +686 +158, WebRtcIsac_kQKltCdfShape +686 +162, WebRtcIsac_kQKltCdfShape +686 +167,
+WebRtcIsac_kQKltCdfShape +686 +173, WebRtcIsac_kQKltCdfShape +686 +179, WebRtcIsac_kQKltCdfShape +686 +186, WebRtcIsac_kQKltCdfShape +686 +194, WebRtcIsac_kQKltCdfShape +686 +205, WebRtcIsac_kQKltCdfShape +686 +207, WebRtcIsac_kQKltCdfShape +686 +209, WebRtcIsac_kQKltCdfShape +686 +211, WebRtcIsac_kQKltCdfShape +686 +214, WebRtcIsac_kQKltCdfShape +686 +218,
+WebRtcIsac_kQKltCdfShape +686 +222, WebRtcIsac_kQKltCdfShape +686 +226, WebRtcIsac_kQKltCdfShape +686 +230, WebRtcIsac_kQKltCdfShape +686 +234, WebRtcIsac_kQKltCdfShape +686 +238, WebRtcIsac_kQKltCdfShape +686 +242, WebRtcIsac_kQKltCdfShape +686 +247, WebRtcIsac_kQKltCdfShape +686 +253, WebRtcIsac_kQKltCdfShape +686 +262, WebRtcIsac_kQKltCdfShape +686 +269,
+WebRtcIsac_kQKltCdfShape +686 +278, WebRtcIsac_kQKltCdfShape +686 +289, WebRtcIsac_kQKltCdfShape +686 +305, WebRtcIsac_kQKltCdfShape +686 +307, WebRtcIsac_kQKltCdfShape +686 +309, WebRtcIsac_kQKltCdfShape +686 +311, WebRtcIsac_kQKltCdfShape +686 +315, WebRtcIsac_kQKltCdfShape +686 +319, WebRtcIsac_kQKltCdfShape +686 +323, WebRtcIsac_kQKltCdfShape +686 +327,
+WebRtcIsac_kQKltCdfShape +686 +331, WebRtcIsac_kQKltCdfShape +686 +335, WebRtcIsac_kQKltCdfShape +686 +340, WebRtcIsac_kQKltCdfShape +686 +346, WebRtcIsac_kQKltCdfShape +686 +354, WebRtcIsac_kQKltCdfShape +686 +362, WebRtcIsac_kQKltCdfShape +686 +374, WebRtcIsac_kQKltCdfShape +686 +384, WebRtcIsac_kQKltCdfShape +686 +396, WebRtcIsac_kQKltCdfShape +686 +413,
+WebRtcIsac_kQKltCdfShape +686 +439, WebRtcIsac_kQKltCdfShape +686 +442, WebRtcIsac_kQKltCdfShape +686 +446, WebRtcIsac_kQKltCdfShape +686 +450, WebRtcIsac_kQKltCdfShape +686 +455, WebRtcIsac_kQKltCdfShape +686 +461, WebRtcIsac_kQKltCdfShape +686 +468, WebRtcIsac_kQKltCdfShape +686 +475, WebRtcIsac_kQKltCdfShape +686 +481, WebRtcIsac_kQKltCdfShape +686 +489,
+WebRtcIsac_kQKltCdfShape +686 +498, WebRtcIsac_kQKltCdfShape +686 +508, WebRtcIsac_kQKltCdfShape +686 +522, WebRtcIsac_kQKltCdfShape +686 +534, WebRtcIsac_kQKltCdfShape +686 +554, WebRtcIsac_kQKltCdfShape +686 +577, WebRtcIsac_kQKltCdfShape +686 +602, WebRtcIsac_kQKltCdfShape +686 +631},
+{WebRtcIsac_kQKltCdfShape +1368 +0, WebRtcIsac_kQKltCdfShape +1368 +2, WebRtcIsac_kQKltCdfShape +1368 +4, WebRtcIsac_kQKltCdfShape +1368 +6, WebRtcIsac_kQKltCdfShape +1368 +8, WebRtcIsac_kQKltCdfShape +1368 +10, WebRtcIsac_kQKltCdfShape +1368 +12, WebRtcIsac_kQKltCdfShape +1368 +14, WebRtcIsac_kQKltCdfShape +1368 +16, WebRtcIsac_kQKltCdfShape +1368 +20,
+WebRtcIsac_kQKltCdfShape +1368 +24, WebRtcIsac_kQKltCdfShape +1368 +28, WebRtcIsac_kQKltCdfShape +1368 +32, WebRtcIsac_kQKltCdfShape +1368 +36, WebRtcIsac_kQKltCdfShape +1368 +40, WebRtcIsac_kQKltCdfShape +1368 +44, WebRtcIsac_kQKltCdfShape +1368 +50, WebRtcIsac_kQKltCdfShape +1368 +57, WebRtcIsac_kQKltCdfShape +1368 +65, WebRtcIsac_kQKltCdfShape +1368 +67,
+WebRtcIsac_kQKltCdfShape +1368 +69, WebRtcIsac_kQKltCdfShape +1368 +71, WebRtcIsac_kQKltCdfShape +1368 +73, WebRtcIsac_kQKltCdfShape +1368 +75, WebRtcIsac_kQKltCdfShape +1368 +77, WebRtcIsac_kQKltCdfShape +1368 +79, WebRtcIsac_kQKltCdfShape +1368 +81, WebRtcIsac_kQKltCdfShape +1368 +85, WebRtcIsac_kQKltCdfShape +1368 +89, WebRtcIsac_kQKltCdfShape +1368 +93,
+WebRtcIsac_kQKltCdfShape +1368 +97, WebRtcIsac_kQKltCdfShape +1368 +101, WebRtcIsac_kQKltCdfShape +1368 +105, WebRtcIsac_kQKltCdfShape +1368 +110, WebRtcIsac_kQKltCdfShape +1368 +116, WebRtcIsac_kQKltCdfShape +1368 +123, WebRtcIsac_kQKltCdfShape +1368 +132, WebRtcIsac_kQKltCdfShape +1368 +134, WebRtcIsac_kQKltCdfShape +1368 +136, WebRtcIsac_kQKltCdfShape +1368 +138,
+WebRtcIsac_kQKltCdfShape +1368 +141, WebRtcIsac_kQKltCdfShape +1368 +143, WebRtcIsac_kQKltCdfShape +1368 +146, WebRtcIsac_kQKltCdfShape +1368 +150, WebRtcIsac_kQKltCdfShape +1368 +154, WebRtcIsac_kQKltCdfShape +1368 +158, WebRtcIsac_kQKltCdfShape +1368 +162, WebRtcIsac_kQKltCdfShape +1368 +166, WebRtcIsac_kQKltCdfShape +1368 +170, WebRtcIsac_kQKltCdfShape +1368 +174,
+WebRtcIsac_kQKltCdfShape +1368 +179, WebRtcIsac_kQKltCdfShape +1368 +185, WebRtcIsac_kQKltCdfShape +1368 +193, WebRtcIsac_kQKltCdfShape +1368 +203, WebRtcIsac_kQKltCdfShape +1368 +214, WebRtcIsac_kQKltCdfShape +1368 +216, WebRtcIsac_kQKltCdfShape +1368 +218, WebRtcIsac_kQKltCdfShape +1368 +220, WebRtcIsac_kQKltCdfShape +1368 +224, WebRtcIsac_kQKltCdfShape +1368 +227,
+WebRtcIsac_kQKltCdfShape +1368 +231, WebRtcIsac_kQKltCdfShape +1368 +235, WebRtcIsac_kQKltCdfShape +1368 +239, WebRtcIsac_kQKltCdfShape +1368 +243, WebRtcIsac_kQKltCdfShape +1368 +247, WebRtcIsac_kQKltCdfShape +1368 +251, WebRtcIsac_kQKltCdfShape +1368 +256, WebRtcIsac_kQKltCdfShape +1368 +262, WebRtcIsac_kQKltCdfShape +1368 +269, WebRtcIsac_kQKltCdfShape +1368 +277,
+WebRtcIsac_kQKltCdfShape +1368 +286, WebRtcIsac_kQKltCdfShape +1368 +297, WebRtcIsac_kQKltCdfShape +1368 +315, WebRtcIsac_kQKltCdfShape +1368 +317, WebRtcIsac_kQKltCdfShape +1368 +319, WebRtcIsac_kQKltCdfShape +1368 +323, WebRtcIsac_kQKltCdfShape +1368 +327, WebRtcIsac_kQKltCdfShape +1368 +331, WebRtcIsac_kQKltCdfShape +1368 +335, WebRtcIsac_kQKltCdfShape +1368 +339,
+WebRtcIsac_kQKltCdfShape +1368 +343, WebRtcIsac_kQKltCdfShape +1368 +349, WebRtcIsac_kQKltCdfShape +1368 +355, WebRtcIsac_kQKltCdfShape +1368 +361, WebRtcIsac_kQKltCdfShape +1368 +368, WebRtcIsac_kQKltCdfShape +1368 +376, WebRtcIsac_kQKltCdfShape +1368 +385, WebRtcIsac_kQKltCdfShape +1368 +397, WebRtcIsac_kQKltCdfShape +1368 +411, WebRtcIsac_kQKltCdfShape +1368 +429,
+WebRtcIsac_kQKltCdfShape +1368 +456, WebRtcIsac_kQKltCdfShape +1368 +459, WebRtcIsac_kQKltCdfShape +1368 +463, WebRtcIsac_kQKltCdfShape +1368 +467, WebRtcIsac_kQKltCdfShape +1368 +473, WebRtcIsac_kQKltCdfShape +1368 +478, WebRtcIsac_kQKltCdfShape +1368 +485, WebRtcIsac_kQKltCdfShape +1368 +491, WebRtcIsac_kQKltCdfShape +1368 +497, WebRtcIsac_kQKltCdfShape +1368 +505,
+WebRtcIsac_kQKltCdfShape +1368 +514, WebRtcIsac_kQKltCdfShape +1368 +523, WebRtcIsac_kQKltCdfShape +1368 +535, WebRtcIsac_kQKltCdfShape +1368 +548, WebRtcIsac_kQKltCdfShape +1368 +565, WebRtcIsac_kQKltCdfShape +1368 +585, WebRtcIsac_kQKltCdfShape +1368 +611, WebRtcIsac_kQKltCdfShape +1368 +640}};
+
+/* code length for all coefficients using different models */
+const double WebRtcIsac_kQKltCodeLenGain[392] = {
+ 12.29956028, 7.83007500, 4.25642781, 0.17489215, 4.27591254, 7.66908312, 10.47643804, 11.91253716, 9.03421572, 8.57373525,
+ 6.73555740, 5.41409855, 3.65237863, 0.42623449, 3.22418399, 5.68145719, 7.14201900, 8.20558413, 9.34178852, 13.00000000,
+ 13.00000000, 9.47643804, 6.71459778, 3.55472644, 0.28457419, 3.70652835, 7.41128536, 11.60768258, 14.00000000, 12.29956028,
+ 9.29956028, 8.02845645, 6.54878889, 5.07667251, 2.87749552, 0.65310542, 3.11316029, 4.87911416, 5.89540125, 6.76398581,
+ 7.70537925, 9.67807191, 11.14201900, 14.00000000, 14.00000000, 12.29956028, 9.69621925, 7.70537925, 5.49915812, 2.67441345,
+ 0.63381441, 2.74999773, 5.76877882, 8.41503750, 10.75207249, 14.00000000, 9.60768258, 8.85025288, 8.09913319, 7.09010692,
+ 6.36337538, 5.46667027, 4.51618422, 2.64189829, 1.21843537, 2.43823474, 3.89409149, 4.99718498, 6.00989604, 6.78325414,
+ 7.39637366, 8.76159526, 10.60768258, 11.67807191, 12.29956028, 9.54056838, 7.95560588, 5.63040265, 3.81264793, 2.18521728,
+ 1.33727600, 2.37909290, 3.94981123, 5.52426657, 7.32051990, 8.84012866, 11.35614381, 13.00000000, 12.29956028, 11.35614381,
+ 11.35614381, 10.24511250, 9.12963528, 8.80032766, 7.97763219, 7.83007500, 7.09913319, 6.68711704, 6.41879942, 5.74379131,
+ 5.25096862, 4.43061904, 3.54492969, 2.72664147, 2.16306204, 2.71142226, 3.34357514, 4.07444556, 4.95151313, 5.68145719,
+ 6.12041675, 6.55085135, 7.00282052, 7.55705650, 8.44541115, 9.41503750, 10.91253716, 11.60768258, 14.00000000, 14.00000000,
+ 13.00000000, 11.60768258, 10.47643804, 8.80032766, 7.38161450, 6.52426657, 5.47447919, 4.53749773, 3.92719747, 3.41058292,
+ 2.88495635, 2.79344346, 2.85805254, 3.18261657, 3.57216340, 4.08225499, 4.74438125, 5.51215997, 6.30477171, 7.15450995,
+ 8.28575448, 9.69621925, 11.60768258, 13.00000000, 13.67807191, 15.00000000, 15.00000000, 14.00000000, 12.41503750, 11.29956028,
+ 12.41503750, 11.60768258, 10.11735695, 9.47643804, 9.12963528, 9.41503750, 8.23181568, 7.97763219, 7.82507432, 7.50814690,
+ 7.33466408, 6.99157138, 6.95834085, 6.80524315, 6.47447919, 6.35614381, 6.02128954, 5.71459778, 5.58109327, 5.05821876,
+ 4.94539568, 4.59220115, 4.27591254, 4.01522554, 3.89376424, 3.83760867, 3.73321346, 3.74674342, 3.90493270, 4.18942837,
+ 4.33599724, 4.42446075, 4.81760565, 5.07667251, 5.54570071, 5.95697272, 6.46667027, 6.91253716, 7.33466408, 7.82507432,
+ 8.05163277, 9.12963528, 9.02272008, 9.77118131, 9.60768258, 10.11735695, 12.00000000, 12.83007500, 15.00000000, 15.00000000,
+ 14.00000000, 15.00000000, 11.75207249, 12.29956028, 10.95560588, 9.93391081, 9.02272008, 8.00564656, 7.82507432, 7.28919357,
+ 6.77599833, 6.56745810, 6.19910010, 6.23347109, 5.67694524, 5.41879942, 4.96039548, 4.88170777, 4.60768258, 4.52883287,
+ 4.28876323, 4.17583679, 4.21332197, 4.14474217, 4.16119001, 4.12809476, 4.18501706, 4.28489599, 4.35299136, 4.60286019,
+ 4.63040265, 4.81017544, 5.00989604, 5.33822190, 5.43489792, 5.84644797, 6.13272126, 6.75444729, 7.36337538, 7.96108101,
+ 8.54056838, 9.28575448, 9.12963528, 9.47643804, 10.75207249, 12.29956028, 12.41503750, 11.14201900, 12.83007500, 15.00000000,
+ 15.00000000, 15.00000000, 15.00000000, 15.00000000, 15.00000000, 14.00000000, 15.00000000, 15.00000000, 15.00000000, 15.00000000,
+ 13.67807191, 12.41503750, 11.91253716, 11.60768258, 12.29956028, 13.00000000, 12.29956028, 10.95560588, 10.60768258, 9.77118131,
+ 10.02272008, 10.11735695, 10.14201900, 10.75207249, 10.75207249, 9.69621925, 9.47643804, 9.75207249, 8.72387559, 8.47643804,
+ 8.68711704, 8.40754296, 8.20558413, 8.26529038, 7.84518189, 7.89147554, 7.64685317, 7.41128536, 7.33466408, 7.42635281,
+ 7.24845594, 7.11430363, 7.07518750, 7.07518750, 6.70537925, 6.64906082, 6.73555740, 6.62931259, 6.50015411, 6.26190774,
+ 6.36337538, 6.19264508, 5.95151313, 6.08860801, 5.91253716, 5.83007500, 5.68145719, 5.67244736, 5.82632286, 6.00282052,
+ 5.65348627, 5.74970158, 5.87846648, 5.69052365, 5.64464890, 5.58531476, 5.81512466, 5.57688409, 5.87329553, 5.62170514,
+ 5.74851759, 5.81017544, 5.64464890, 5.76398581, 5.60339522, 5.69507833, 5.84139031, 5.68711704, 5.73908047, 5.84139031,
+ 5.71459778, 5.96245305, 5.82632286, 5.89540125, 6.08860801, 6.12041675, 6.13272126, 6.30477171, 6.24177679, 6.28232358,
+ 6.29091619, 6.53239445, 6.81512466, 6.72620440, 6.65792533, 6.84518189, 7.10215454, 7.44157929, 7.57793523, 7.59485854,
+ 7.66460965, 8.05163277, 8.00564656, 8.43775758, 8.10518224, 8.28575448, 8.77118131, 8.23181568, 8.29264087, 8.20558413,
+ 8.34894831, 8.89147554, 8.40754296, 8.61629571, 8.64244800, 8.61629571, 8.93391081, 8.50814690, 9.02272008, 8.68711704,
+ 8.65127185, 9.41503750, 9.11735695, 9.85025288, 10.24511250, 10.60768258, 10.47643804, 11.60768258, 11.35614381, 12.29956028,
+ 15.00000000, 15.00000000, 12.29956028, 13.00000000, 15.00000000, 15.00000000, 15.00000000, 15.00000000, 14.00000000, 12.83007500,
+ 15.00000000, 15.00000000};
+
+const double WebRtcIsac_kQKltCodeLenShape[578] = {
+ 0.00002201, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 14.00000000,
+ 0.00011007, 13.00000000, 0.00066056, 11.60768258, 11.14201900, 0.00185034, 10.24511250, 9.08113676, 0.00480700, 9.41503750,
+ 8.09913319, 0.01084946, 8.02845645, 13.00000000, 6.40941295, 0.02926496, 6.95560588, 13.00000000, 13.00000000, 6.21864029,
+ 0.03861814, 6.30477171, 12.29956028, 11.14201900, 4.66964328, 0.12158980, 4.62604734, 10.91253716, 14.00000000, 11.35614381,
+ 8.76159526, 3.89671219, 0.21179147, 3.99472634, 8.02272008, 13.00000000, 0.00002201, 0.00002201, 0.00002201, 0.00002201,
+ 14.00000000, 0.00011007, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 14.00000000, 0.00011007, 10.95560588, 0.00147568,
+ 10.95560588, 10.24511250, 0.00240150, 10.24511250, 8.02845645, 0.01056115, 8.17982104, 6.74497143, 0.02381629, 7.15137706,
+ 5.68598330, 0.05650076, 5.72970467, 13.00000000, 14.00000000, 5.18221688, 0.07697435, 5.37611851, 11.91253716, 9.54056838,
+ 3.92853764, 0.22143514, 3.76428491, 9.28575448, 14.00000000, 11.35614381, 7.37794818, 3.30585980, 0.37001735, 3.18521728,
+ 6.88886433, 11.91253716, 14.00000000, 0.00002201, 0.00002201, 0.00002201, 0.00002201, 14.00000000, 0.00019814, 14.00000000,
+ 0.00002201, 13.00000000, 0.00028621, 14.00000000, 14.00000000, 0.00028621, 13.00000000, 11.91253716, 0.00094690, 11.35614381,
+ 10.60768258, 0.00213692, 10.24511250, 8.37794818, 0.00863317, 8.43775758, 14.00000000, 7.41128536, 0.01698415, 7.42635281,
+ 6.02702021, 0.04514485, 6.01558154, 13.00000000, 5.05090284, 0.09207659, 4.98877274, 15.00000000, 10.75207249, 4.41081703,
+ 0.15733047, 4.17424617, 11.60768258, 14.00000000, 15.00000000, 10.06926266, 3.74320161, 0.23091117, 3.81141115, 10.02272008,
+ 11.91253716, 6.90196792, 2.92703003, 0.46874039, 2.93846004, 7.26190774, 11.60768258, 13.00000000, 10.21864029, 7.95560588,
+ 5.19345038, 2.40520888, 0.77554605, 2.56628417, 5.41409855, 8.81017544, 12.29956028, 0.00002201, 0.00002201, 0.00002201,
+ 0.00002201, 11.91253716, 0.00068259, 12.29956028, 10.11735695, 0.00233535, 10.47643804, 10.35614381, 0.00140957, 12.29956028,
+ 10.24511250, 0.00222511, 10.47643804, 7.72387559, 0.01475842, 7.52426657, 6.73555740, 0.02924249, 6.55085135, 14.00000000,
+ 5.45021533, 0.06930886, 5.38345116, 4.55913083, 0.11289841, 4.92853764, 11.60768258, 4.07148162, 0.19798859, 3.87200568,
+ 13.00000000, 9.60768258, 3.31393725, 0.29937064, 3.57321111, 9.35614381, 14.00000000, 8.02845645, 3.08542800, 0.45503557,
+ 2.80678268, 7.47643804, 12.29956028, 14.00000000, 14.00000000, 14.00000000, 6.83509307, 2.69166097, 0.61673447, 2.51266238,
+ 6.84771516, 11.91253716, 11.14201900, 7.72387559, 4.61899789, 2.17136763, 1.03592993, 2.28586183, 4.86814304, 7.78568088,
+ 10.91253716, 14.00000000, 15.00000000, 11.04580369, 9.28575448, 7.26190774, 5.21946023, 3.61575588, 2.18431651, 1.45666604,
+ 2.33566383, 3.85470467, 5.46181107, 7.30651304, 8.89147554, 11.91253716, 0.00002201, 0.00002201, 15.00000000, 0.00011007,
+ 15.00000000, 10.47643804, 0.00149771, 11.60768258, 7.30651304, 0.01903486, 7.20558413, 6.92318440, 0.02587674, 6.71459778,
+ 7.28919357, 0.01756340, 7.45696818, 6.06926266, 0.03841465, 6.45890338, 4.46035649, 0.13896157, 4.43204392, 14.00000000,
+ 14.00000000, 4.09010692, 0.19672654, 3.86653665, 13.00000000, 14.00000000, 11.35614381, 3.45117809, 0.27340929, 3.64878468,
+ 9.93391081, 9.60768258, 3.30585980, 0.35178287, 3.15607895, 9.12963528, 12.29956028, 7.93391081, 2.82180202, 0.53064436,
+ 2.68258739, 7.42635281, 11.14201900, 15.00000000, 10.06926266, 6.15294265, 2.55861197, 0.69308389, 2.48602573, 5.90592231,
+ 9.47643804, 13.00000000, 11.14201900, 8.20558413, 5.21618324, 2.34973357, 1.00379135, 2.09611815, 4.80278331, 7.82507432,
+ 11.91253716, 12.29956028, 8.98877274, 6.75444729, 4.23886435, 2.19859476, 1.29528579, 2.06032897, 4.06704711, 6.76398581,
+ 9.34178852, 13.00000000, 12.29956028, 10.14201900, 8.40754296, 6.16710999, 4.64850859, 3.28768796, 2.22892326, 1.78568088,
+ 2.35209193, 3.45141888, 4.91121176, 6.45117809, 8.20558413, 10.35614381, 13.00000000, 12.83007500, 14.00000000, 14.00000000,
+ 12.83007500, 11.35614381, 9.85025288, 9.41503750, 8.07518750, 7.34894831, 6.25516616, 5.25096862, 4.52477322, 3.68513357,
+ 3.06152306, 2.64011320, 2.54608637, 2.95765662, 3.44445223, 4.01665007, 4.63258525, 5.27633906, 6.24678325, 7.05163277,
+ 8.02845645, 9.60768258, 10.79054663, 12.83007500, 14.00000000, 0.00002201, 15.00000000, 0.00011007, 15.00000000, 5.82009091,
+ 0.02710994, 10.11735695, 15.00000000, 3.30346709, 0.17317845, 6.41128536, 15.00000000, 15.00000000, 10.83007500, 2.72897475,
+ 0.35935964, 3.85853144, 13.00000000, 15.00000000, 3.72766182, 0.17268211, 4.74674342, 15.00000000, 15.00000000, 4.40754296,
+ 0.11993823, 4.93997965, 15.00000000, 15.00000000, 4.70193743, 0.22110152, 3.27591254, 11.35614381, 15.00000000, 12.54056838,
+ 6.94743195, 2.99157138, 0.62079088, 2.25338071, 7.41128536, 15.00000000, 15.00000000, 11.47643804, 6.04580369, 2.80232255,
+ 0.98380109, 1.70502034, 5.15607895, 10.75207249, 13.00000000, 15.00000000, 15.00000000, 11.35614381, 6.44157929, 2.37955105,
+ 0.74567258, 2.44181848, 6.07667251, 10.75207249, 15.00000000, 15.00000000, 15.00000000, 15.00000000, 9.44541115, 5.25432568,
+ 1.97815248, 0.94086682, 2.57885561, 5.17265730, 8.72387559, 14.00000000, 15.00000000, 15.00000000, 15.00000000, 10.67807191,
+ 7.59485854, 4.91187431, 2.91934900, 1.32321648, 1.50614455, 3.85215911, 7.15137706, 10.60768258, 14.00000000, 15.00000000,
+ 15.00000000, 15.00000000, 15.00000000, 15.00000000, 15.00000000, 15.00000000, 11.09310940, 8.50814690, 6.45117809, 3.94675287,
+ 2.16730774, 1.37674720, 2.10215454, 3.97278511, 6.34178852, 8.50814690, 10.32757466, 14.00000000, 14.00000000, 15.00000000,
+ 15.00000000, 15.00000000, 14.00000000, 10.02272008, 9.41503750, 7.03710399, 5.13349379, 3.61683574, 2.47999526, 1.82788507,
+ 2.00945280, 3.08020557, 4.69793233, 6.64025044, 8.32051990, 10.91253716, 14.00000000, 15.00000000, 15.00000000, 15.00000000,
+ 15.00000000, 15.00000000, 15.00000000, 14.41503750, 9.41503750, 7.10215454, 5.60768258, 4.44014496, 3.30064444, 2.56941678,
+ 2.28103909, 2.42694459, 2.93206152, 3.83383692, 4.75207249, 6.02702021, 7.16394964, 9.35614381, 11.14201900, 12.29956028,
+ 15.00000000, 15.00000000, 14.00000000, 15.00000000, 15.00000000, 10.11735695, 8.85025288, 7.02558541, 5.86300889, 4.79726396,
+ 3.95117259, 3.44925321, 2.96348293, 2.88219459, 2.89671219, 3.10518224, 3.50065237, 4.05748549, 4.55291677, 5.23016216,
+ 5.79420675, 6.39452048, 6.91253716, 7.97763219, 8.32051990, 9.35614381, 10.60768258, 11.60768258, 15.00000000, 15.00000000,
+ 12.83007500, 12.41503750, 11.91253716, 14.00000000, 14.00000000, 11.35614381, 10.75207249, 10.91253716, 8.93391081, 8.61629571,
+ 8.29264087, 8.02272008, 7.89147554, 7.33466408, 7.41128536, 6.71459778, 5.92853764, 5.31964048, 4.97693875, 4.70308379,
+ 4.43632704, 4.34357514, 4.30825648, 4.26529038, 4.19465917, 4.27420773, 4.22315577, 4.08262792, 4.06667818, 4.16119001,
+ 4.08860801, 4.26698468, 4.39128315, 4.71517590, 5.10442472, 5.50714538, 5.81017544, 6.15922208};
+
+/* left KLT transforms */
+const double WebRtcIsac_kKltT1Gain[3][4] = {
+{-0.79742827, 0.60341375, 0.60341375, 0.79742827},
+{-0.81372390, 0.58125159, 0.58125159, 0.81372390},
+{-0.71832547, 0.69570721, 0.69570721, 0.71832547}};
+
+const double WebRtcIsac_kKltT1Shape[3][324] = {
+{ 0.00159597, 0.00049320, 0.00513821, 0.00021066, 0.01338581, -0.00422367, -0.00272072, 0.00935107, 0.02047622, 0.02691189,
+ 0.00478236, 0.03969702, 0.00886698, 0.04877604, -0.10898362, -0.05930891, -0.03415047, 0.98889721, 0.00293558, -0.00035282,
+ 0.01156321, -0.00195341, -0.00937631, 0.01052213, -0.02551163, 0.01644059, 0.03189927, 0.07754773, -0.08742313, -0.03026338,
+ 0.05136248, -0.14395974, 0.17725040, 0.22664856, 0.93380230, 0.07076411, 0.00557890, -0.00222834, 0.01377569, 0.01466808,
+ 0.02847361, -0.00603178, 0.02382480, -0.01210452, 0.03797267, -0.02371480, 0.11260335, -0.07366682, 0.00453436, -0.04136941,
+-0.07912843, -0.95031418, 0.25295337, -0.05302216, -0.00617554, -0.00044040, -0.00653778, 0.01097838, 0.01529174, 0.01374431,
+-0.00748512, -0.00020034, 0.02432713, 0.11101570, -0.08556891, 0.09282249, -0.01029446, 0.67556443, -0.67454300, 0.06910063,
+ 0.20866865, -0.10318050, 0.00932175, 0.00524058, 0.00803610, -0.00594676, -0.01082578, 0.01069906, 0.00546768, 0.01565291,
+ 0.06816200, 0.10201227, 0.16812734, 0.22984074, 0.58213170, -0.54138651, -0.51379962, 0.06847390, -0.01920037, -0.04592324,
+-0.00467394, 0.00328858, 0.00377424, -0.00987448, 0.08222096, -0.00377301, 0.04551941, -0.02592517, 0.16317082, 0.13077530,
+ 0.22702921, -0.31215289, -0.69645962, -0.38047101, -0.39339411, 0.11124777, 0.02508035, -0.00708074, 0.00400344, 0.00040331,
+ 0.01142402, 0.01725406, 0.01635170, 0.14285366, 0.03949233, -0.05905676, 0.05877154, -0.17497577, -0.32479440, 0.80754464,
+-0.38085603, -0.17055430, -0.03168622, -0.07531451, 0.02942002, -0.02148095, -0.00754114, -0.00322372, 0.00567812, -0.01701521,
+-0.12358320, 0.11473564, 0.09070136, 0.06533068, -0.22560802, 0.19209022, 0.81605094, 0.36592275, -0.09919829, 0.16667122,
+ 0.16300725, 0.04803807, 0.06739263, -0.00156752, -0.01685302, -0.00905240, -0.02297836, -0.00469939, 0.06310613, -0.16391930,
+ 0.10919511, 0.12529293, 0.85581322, -0.32145522, 0.24539076, 0.07181839, 0.07289591, 0.14066759, 0.10406711, 0.05815518,
+ 0.01072680, -0.00759339, 0.00053486, -0.00044865, 0.03407361, 0.01645348, 0.08758579, 0.27722240, 0.53665485, -0.74853376,
+-0.01118192, -0.19805430, 0.06130619, -0.09675299, 0.08978480, 0.03405255, -0.00706867, 0.05102045, 0.03250746, 0.01849966,
+-0.01216314, -0.01184187, -0.01579288, 0.00114807, 0.11376166, 0.88342114, -0.36425379, 0.13863190, 0.12524180, -0.13553892,
+ 0.04715856, -0.12341103, 0.04531568, 0.01899360, -0.00206897, 0.00567768, -0.01444163, 0.00411946, -0.00855896, 0.00381663,
+-0.01664861, -0.05534280, 0.21328278, 0.20161162, 0.72360394, 0.59130708, -0.08043791, 0.08757349, -0.13893918, -0.05147377,
+ 0.02680690, -0.01144070, 0.00625162, -0.00634215, -0.01248947, -0.00329455, -0.00609625, -0.00136305, -0.05097048, -0.01029851,
+ 0.25065384, -0.16856837, -0.07123372, 0.15992623, -0.39487617, -0.79972301, 0.18118185, -0.04826639, -0.01805578, -0.02927253,
+-0.16400618, 0.07472763, 0.10376449, 0.01705406, 0.01065801, -0.01500498, 0.02039914, 0.37776349, -0.84484186, 0.10434286,
+ 0.15616990, 0.13474456, -0.00906238, -0.25238368, -0.03820885, -0.10650905, -0.03880833, -0.03660028, -0.09640894, 0.00583314,
+ 0.01922097, 0.01489911, -0.02431117, -0.09372217, 0.39404721, -0.84786223, -0.31277121, 0.03193850, 0.01974060, 0.01887901,
+ 0.00337911, -0.11359599, -0.02792521, -0.03220184, -0.01533311, 0.00015962, -0.04225043, -0.00933965, 0.00675311, 0.00206060,
+ 0.15926771, 0.40199829, -0.80792558, -0.35591604, -0.17169764, 0.02830436, 0.02459982, -0.03438589, 0.00718705, -0.01798329,
+-0.01594508, -0.00702430, -0.00952419, -0.00962701, -0.01307212, -0.01749740, 0.01299602, 0.00587270, -0.36103108, -0.82039266,
+-0.43092844, -0.08500097, -0.04361674, -0.00333482, 0.01250434, -0.02538295, -0.00921797, 0.01645071, -0.01400872, 0.00317607,
+ 0.00003277, -0.01617646, -0.00616863, -0.00882661, 0.00466157, 0.00353237, 0.91803104, -0.39503305, -0.02048964, 0.00060125,
+ 0.01980634, 0.00300109, 0.00313880, 0.00657337, 0.00715163, 0.00000261, 0.00854276, -0.00154825, -0.00516128, 0.00909527,
+ 0.00095609, 0.00701196, -0.00221867, -0.00156741},
+{-0.00469582, -0.00020403, -0.00587134, 0.00185153, -0.02256479, -0.01185761, -0.02891481, -0.00493792, -0.00182344, 0.00285962,
+ 0.01558059, -0.02185140, 0.04639438, -0.04357142, 0.12718613, -0.06756136, 0.05542227, 0.98480184, -0.00374376, -0.00236433,
+-0.00607169, -0.00303290, -0.00127243, -0.01794845, 0.00620033, -0.00732704, -0.02837749, -0.00107164, 0.04820548, 0.00713300,
+ 0.09784244, -0.16806261, -0.04563341, -0.33406041, 0.91554083, -0.08139655, -0.00415851, -0.00538193, -0.00731198, -0.00534534,
+-0.00623075, -0.02016943, -0.05480133, -0.03172290, -0.03879603, 0.01518441, 0.09591688, 0.02238470, 0.08126640, 0.08236821,
+-0.24802119, 0.89516402, 0.32029647, 0.07188887, -0.00220366, 0.00344025, -0.00277284, 0.00358963, -0.08668007, -0.02205910,
+-0.05289669, -0.03535201, -0.01188017, -0.06456872, -0.09321006, -0.00009617, -0.15804070, 0.24632041, 0.90166119, 0.19250690,
+ 0.17264619, -0.09699155, -0.00567329, -0.00897700, -0.01442565, -0.01939390, 0.03702127, -0.02999862, -0.04385696, -0.05232394,
+-0.03339177, 0.03905964, -0.00281424, -0.29213275, 0.02892968, 0.90257613, -0.21546058, -0.18070946, 0.09014567, 0.04117230,
+-0.01029696, -0.00329116, -0.03354346, 0.02937079, 0.01274208, -0.01260649, -0.03505571, -0.01020645, 0.03787209, 0.12132165,
+-0.20826840, 0.81556933, -0.43874351, 0.21518682, -0.14564290, -0.05210031, 0.07124563, 0.06127983, -0.00457321, 0.01740496,
+ 0.04185176, 0.00128036, -0.05033693, -0.01890046, 0.06221734, 0.10280078, -0.03738531, 0.04830209, -0.08408293, -0.46409009,
+-0.83936263, -0.14817619, -0.13135927, 0.04563506, 0.08340661, 0.04040200, 0.00044396, -0.01365972, 0.01228951, 0.01078273,
+ 0.09205406, -0.03791500, 0.07135889, 0.08158339, 0.06298278, -0.22875755, -0.92917558, -0.11248260, 0.17801883, -0.03971674,
+-0.07491915, 0.06477287, 0.04635713, 0.01856159, 0.00130895, -0.01991604, 0.02358176, -0.09376056, 0.02782280, -0.04691559,
+ 0.13749249, 0.31383132, 0.92274602, 0.04727419, 0.09765196, -0.02108945, 0.00626005, 0.05193322, 0.02009133, 0.03094066,
+ 0.04573470, 0.00451733, 0.00240169, -0.00982355, -0.03546208, -0.14156875, -0.02480689, 0.22997442, 0.09778317, 0.88834235,
+-0.32797611, -0.00079977, 0.04917079, 0.06977359, 0.06451185, 0.07816204, 0.03119314, 0.01136506, 0.01062006, 0.00632783,
+ 0.03241828, -0.03318847, -0.01350502, -0.30055361, 0.07265375, 0.17308022, 0.88795796, -0.23231020, -0.08932700, 0.11759604,
+ 0.00590705, 0.03525351, 0.00840466, 0.04389942, 0.04387629, 0.04003275, 0.01772966, 0.02709780, -0.02393282, 0.02766178,
+ 0.00342983, -0.33882220, 0.76612668, 0.44061716, -0.28414784, -0.09364014, 0.03694060, 0.01124120, 0.01130268, -0.02869682,
+-0.07428963, -0.03504754, 0.05874942, 0.01196795, 0.02003875, 0.00787152, -0.01605561, 0.04501257, -0.06959958, -0.13015784,
+-0.05738065, 0.04681625, 0.06668700, -0.04492094, 0.02927765, -0.94404277, 0.19243952, 0.09504337, -0.12540826, 0.05394317,
+-0.07972638, -0.02145188, 0.00136427, 0.01964678, 0.06667373, 0.06204535, 0.17302394, 0.22005905, 0.58329964, -0.68440447,
+ 0.19628796, 0.15718011, -0.12481840, -0.08222507, 0.11780870, 0.03798206, -0.01818866, 0.00892766, 0.05582263, 0.01126832,
+-0.00973589, 0.00697442, -0.09937902, 0.06621185, -0.19452202, -0.80004569, -0.13946094, -0.48990700, -0.17595191, -0.00798873,
+-0.06121856, 0.08768040, -0.04507631, 0.00448896, 0.01153941, -0.04711652, -0.01050749, -0.01660047, -0.03007159, -0.01468906,
+ 0.12848053, 0.13859838, 0.93863771, -0.22250065, -0.14841278, 0.04666032, -0.06344813, -0.01915105, -0.01840150, -0.02389410,
+-0.01245496, 0.05023402, 0.02125840, 0.02467318, -0.01893022, -0.00889647, 0.00551817, 0.00481915, -0.40626968, -0.89028236,
+ 0.18261687, -0.03852330, 0.02621926, -0.05420122, -0.01704117, -0.00072893, -0.02694170, -0.04335124, 0.02256467, 0.00642301,
+-0.01619484, -0.00871160, 0.00400065, -0.00488820, -0.00752173, -0.00170603, 0.89554989, -0.41825934, -0.08725803, -0.09051404,
+-0.00916236, -0.02959065, -0.07268075, -0.00816626, -0.00314215, -0.01941078, -0.00036782, -0.00188655, -0.02107724, -0.00771657,
+-0.00448194, -0.00387517, 0.00082998, 0.00202471},
+{ 0.00167296, -0.00647772, -0.00604394, 0.01490810, -0.00837664, 0.00246438, 0.02082153, 0.01216715, 0.01001396, -0.02850860,
+-0.01187868, -0.00113289, 0.04140237, -0.11084998, 0.16102260, 0.20084170, -0.28969446, -0.91312256, 0.00087788, -0.00136895,
+ 0.00004622, 0.00578894, 0.00524119, -0.00044550, 0.00948906, -0.00396910, -0.03312197, -0.00075487, 0.00987494, -0.02088734,
+ 0.09835550, -0.20080342, 0.13687782, -0.16111863, -0.90089988, 0.30312999, 0.00248784, -0.00975419, -0.01617200, 0.00699371,
+-0.02151635, -0.01625774, -0.01262800, 0.02588781, -0.05620764, -0.13651454, 0.04242442, -0.02615307, 0.20497288, -0.20422909,
+ 0.14184406, 0.89712919, 0.01758042, 0.25447787, -0.00207668, -0.00260329, 0.00724812, -0.01007749, 0.00806242, -0.03089729,
+-0.01161934, -0.00618676, -0.10327342, -0.10160272, 0.11919283, 0.20781533, 0.11564869, -0.19072476, 0.86402008, -0.24650846,
+ 0.24684161, 0.04775750, 0.00486888, -0.01735569, -0.01868000, -0.01870386, -0.03243262, -0.05883701, -0.03433371, 0.10441236,
+-0.22831067, -0.22837988, 0.15082544, -0.21313767, 0.13215611, -0.78096079, -0.32270595, -0.21307018, 0.17339271, -0.05435742,
+-0.00940813, 0.00272520, 0.00542917, -0.05232991, -0.01280809, -0.10773627, -0.17626479, 0.03719285, -0.26297104, -0.21780618,
+ 0.21406665, 0.15202177, 0.75911044, 0.38627481, -0.16504189, -0.10242997, -0.02394939, -0.06018959, 0.00994733, -0.02617197,
+-0.01543723, -0.10320051, -0.03010481, -0.19098072, -0.06893233, 0.12253174, -0.25556092, -0.31989059, 0.09542655, 0.72712041,
+-0.43108921, -0.01568072, -0.16532685, 0.06646835, -0.08885408, -0.00050364, -0.01791050, 0.00245405, 0.00204794, -0.17948691,
+-0.05193881, -0.16329387, -0.13676259, 0.01214133, -0.30994612, -0.00687734, 0.63254090, -0.47180795, -0.35409214, 0.23658315,
+ 0.11170294, 0.05229887, -0.06107035, -0.01094212, 0.01523854, -0.01608284, -0.03739206, -0.23864328, -0.03958494, -0.19305719,
+-0.26019058, 0.24108257, -0.55933566, 0.40623396, -0.53367968, -0.08930957, -0.00599383, -0.00050845, 0.06960811, 0.02664961,
+ 0.01464197, -0.00486781, -0.01905736, 0.01437578, 0.02379930, -0.26639588, 0.05208876, -0.43525002, -0.63009424, 0.05251889,
+ 0.56732782, -0.06731164, -0.03705909, -0.03253946, 0.00950673, -0.07941760, 0.02388267, -0.01258409, -0.00343524, 0.00148711,
+-0.00362107, 0.03981813, -0.07235214, -0.46180041, -0.05595288, -0.55699317, 0.61935853, -0.25379716, 0.06796783, 0.01039267,
+-0.06329171, -0.02143024, 0.09406929, -0.00799203, -0.01419805, -0.00603024, 0.01313145, 0.00091161, -0.00212107, -0.02405340,
+ 0.07146405, -0.76695326, -0.14841817, 0.60372663, -0.01478424, 0.06522462, 0.08580016, -0.05817981, 0.02438942, 0.04840904,
+ 0.02934363, -0.02239678, -0.00582247, -0.00091312, -0.00394148, -0.00285276, -0.03435745, 0.05277435, 0.17882781, -0.06194164,
+ 0.27321118, 0.01840179, -0.10188148, -0.33168524, -0.03491221, 0.67351789, 0.37017376, 0.32083717, 0.09737800, -0.20998084,
+-0.10725041, 0.06379186, 0.02169903, -0.02031584, 0.05623799, -0.18300962, -0.17337803, 0.08915172, -0.53835537, -0.08547263,
+ 0.15163321, 0.56732906, 0.21878115, 0.37274266, 0.26206918, 0.13443927, 0.09178695, -0.03276324, -0.01131664, -0.00236369,
+ 0.00772568, 0.01008805, -0.17122615, 0.15301569, 0.40135484, -0.06058913, 0.56405128, -0.05176853, 0.24544337, 0.62448073,
+ 0.07265009, -0.01198695, 0.05151774, -0.03678498, 0.01886154, 0.03724094, 0.01393667, 0.00758055, -0.00254297, 0.00537118,
+ 0.24169707, -0.41735970, -0.67564355, -0.09270478, 0.53106033, 0.06214579, 0.02574404, 0.09943837, 0.03032542, 0.02194476,
+ 0.06369772, -0.00133741, 0.01301113, 0.01508494, 0.00036111, -0.00278870, 0.00139205, 0.00015792, -0.43347887, 0.69923146,
+-0.55406563, -0.01102231, 0.01347767, 0.07012139, -0.02530164, 0.06803192, 0.01177196, 0.04374491, 0.04073027, 0.04037438,
+ 0.00167330, -0.01807065, -0.00425562, 0.00149653, -0.00035119, -0.00172888, 0.84785495, 0.52289580, 0.01067734, -0.00859194,
+ 0.01685964, 0.00481442, 0.00434738, 0.07592695, 0.01419942, 0.01005336, 0.03316937, 0.00360465, 0.00435039, 0.00029122,
+ 0.00171268, 0.00198919, -0.00046889, -0.00094176}};
+
+/* right KLT transforms */
+const double WebRtcIsac_kKltT2Gain[3][36] = {
+{ 0.14572837, -0.45446306, 0.61990621, -0.52197033, 0.32145074, -0.11026900, -0.20698282, 0.48962182, -0.27127933, -0.33627476,
+ 0.65094037, -0.32715751, 0.40262573, -0.47844405, -0.33876075, 0.44130653, 0.37383966, -0.39964662, -0.51730480, 0.06611973,
+ 0.49030187, 0.47512886, -0.02141226, -0.51129451, -0.58578569, -0.39132064, -0.13187771, 0.15649421, 0.40735596, 0.54396897,
+ 0.40381276, 0.40904942, 0.41179766, 0.41167576, 0.40840251, 0.40468132},
+{-0.11368135, 0.34815515, -0.56434996, 0.61130763, -0.39970336, 0.11795708, 0.28514257, -0.58879243, 0.32775812, 0.27024886,
+-0.56251299, 0.27411037, 0.42649186, -0.44080232, -0.36408215, 0.35932457, 0.43592895, -0.41484213, -0.49813030, -0.00012592,
+ 0.49865688, 0.47634953, 0.01094246, -0.52552726, -0.56154082, -0.41110686, -0.14170764, 0.15946614, 0.40818082, 0.55094554,
+ 0.40051601, 0.41084781, 0.41567800, 0.41450700, 0.40871872, 0.39891823},
+{-0.10719481, 0.34796287, -0.54573957, 0.59521001, -0.43943367, 0.14907223, 0.26554957, -0.59549939, 0.36760692, 0.26040652,
+-0.55268701, 0.25778784, 0.38994096, -0.45282773, -0.37975656, 0.40213055, 0.43052647, -0.38937904, -0.52698359, 0.02788094,
+ 0.48284286, 0.47792474, 0.02557759, -0.50922240, -0.57699826, -0.39476779, -0.14708238, 0.12742149, 0.37835245, 0.57464021,
+ 0.39408127, 0.40327462, 0.40993655, 0.41419345, 0.41506301, 0.41253853}};
+
+const double WebRtcIsac_kKltT2Shape[3][36] = {
+{ 0.13427386, -0.35132558, 0.52506528, -0.59419077, 0.45075085, -0.16312057, 0.29857439, -0.58660147, 0.34265431, 0.20879510,
+-0.56063262, 0.30238345, 0.43308283, -0.41186999, -0.35288681, 0.42768996, 0.36094634, -0.45284910, -0.47116680, 0.02893449,
+ 0.54326135, 0.45249040, -0.06264420, -0.52283830, 0.57137758, 0.44298139, 0.12617554, -0.20819946, -0.42324603, -0.48876443,
+ 0.39597050, 0.40713935, 0.41389880, 0.41512486, 0.41130400, 0.40575001},
+{ 0.16540737, -0.43379435, 0.58165221, -0.55154773, 0.35734028, -0.11935912, 0.29434254, -0.55954817, 0.23549804, 0.33087258,
+-0.58848503, 0.29835834, 0.45464789, -0.38316155, -0.41689708, 0.35607296, 0.41260747, -0.41910198, -0.48633899, -0.04144955,
+ 0.47824583, 0.51050942, 0.01000345, -0.52184032, 0.53488229, 0.42641051, 0.17049774, -0.15849613, -0.43229355, -0.53945045,
+ 0.39582002, 0.41033103, 0.41788713, 0.41688080, 0.41081697, 0.39719658},
+{ 0.13386268, -0.37919915, 0.54989123, -0.57663572, 0.42402636, -0.15362720, 0.29641577, -0.58806770, 0.31381040, 0.26524954,
+-0.56271012, 0.28431868, 0.42699898, -0.41058922, -0.40408270, 0.39215865, 0.40788513, -0.40699735, -0.49846482, -0.01521208,
+ 0.48756040, 0.49479418, -0.00347672, -0.51841384, 0.55513106, 0.41683793, 0.15131217, -0.15613621, -0.41029341, -0.54996461,
+ 0.39402116, 0.40965305, 0.41862791, 0.41730770, 0.41089648, 0.39837262}};
+
+/* means of log gains and LAR coefficients*/
+const double WebRtcIsac_kLpcMeansGain[3][12] = {
+{-6.86881911, -5.35075273, -6.86792680, -5.36200897, -6.86401538, -5.36921533, -6.86802969, -5.36893966, -6.86538097, -5.36315063,
+-6.85535304, -5.35155315},
+{-6.12914600, -4.78070092, -6.12971780, -4.78382183, -6.12858525, -4.79362198, -6.12926491, -4.79017481, -6.12102401, -4.78346122,
+-6.11441152, -4.78019228},
+{-5.67273484, -3.73876311, -5.65246094, -3.71407895, -5.61716443, -3.68814580, -5.58804560, -3.66334094, -5.54189577, -3.63845640,
+-5.49293185, -3.61760203}};
+
+const double WebRtcIsac_kLpcMeansShape[3][108] = {
+{-0.91232981, 0.26258634, -0.33716701, 0.08477430, -0.03378426, 0.14423909, 0.07036185, 0.06155019, 0.01490385, 0.04138740,
+ 0.01427317, 0.01288970, 0.83872106, 0.25750199, 0.07988929, -0.01957923, 0.00831390, 0.01770300, -0.90957164, 0.25732216,
+-0.33385344, 0.08735740, -0.03715332, 0.14584917, 0.06998990, 0.06131968, 0.01504379, 0.04067339, 0.01428039, 0.01406460,
+ 0.83846243, 0.26169862, 0.08109025, -0.01767055, 0.00970539, 0.01954310, -0.90490803, 0.24656405, -0.33578607, 0.08843286,
+-0.03749139, 0.14443959, 0.07214669, 0.06170993, 0.01449947, 0.04134309, 0.01314762, 0.01413471, 0.83895203, 0.26748062,
+ 0.08197507, -0.01781298, 0.00885967, 0.01922394, -0.90922472, 0.24495889, -0.33921540, 0.08877169, -0.03581332, 0.14199172,
+ 0.07444032, 0.06185940, 0.01502054, 0.04185113, 0.01276579, 0.01355457, 0.83645358, 0.26631720, 0.08119697, -0.01835449,
+ 0.00788512, 0.01846446, -0.90482253, 0.24658310, -0.34019734, 0.08281090, -0.03486038, 0.14359248, 0.07401336, 0.06001471,
+ 0.01528421, 0.04254560, 0.01321472, 0.01240799, 0.83857127, 0.26281654, 0.08174380, -0.02099842, 0.00755176, 0.01699448,
+-0.90132307, 0.25174308, -0.33838268, 0.07883863, -0.02877906, 0.14105407, 0.07220290, 0.06000352, 0.01684879, 0.04226844,
+ 0.01331331, 0.01269244, 0.83832138, 0.25467485, 0.08118028, -0.02120528, 0.00747832, 0.01567212},
+{-1.11639718, 0.35377266, 0.00798929, 0.20165280, 0.07656104, 0.10629964, 0.04894160, 0.10955305, -0.01806405, 0.05082282,
+ 0.01730794, 0.01345957, 0.73717782, 0.05952284, 0.03176204, 0.08195122, 0.01253148, 0.02253385, -1.12053537, 0.35523538,
+ 0.00859646, 0.20007706, 0.07715852, 0.10754596, 0.05165976, 0.10927703, -0.01554395, 0.05178866, 0.01752534, 0.01343468,
+ 0.73489046, 0.06395167, 0.03287798, 0.07972374, 0.01293550, 0.02300929, -1.11772179, 0.35457623, 0.01205524, 0.19926481,
+ 0.08000866, 0.10817921, 0.05052481, 0.11016167, -0.01552091, 0.05155510, 0.01787163, 0.01343778, 0.73142568, 0.06840830,
+ 0.03316828, 0.07902608, 0.01525042, 0.02178127, -1.12120164, 0.36405233, 0.00630305, 0.19799738, 0.07829690, 0.10727588,
+ 0.04017317, 0.10437949, -0.01844109, 0.05021700, 0.01561726, 0.01226571, 0.73438044, 0.06947982, 0.03396317, 0.07858683,
+ 0.01367105, 0.02041955, -1.12146187, 0.35952226, 0.00340090, 0.19700813, 0.07938222, 0.10904137, 0.03921216, 0.10531403,
+-0.01833415, 0.04956231, 0.01399539, 0.01323582, 0.74378099, 0.07059589, 0.03367692, 0.08151462, 0.01182040, 0.02075577,
+-1.11245254, 0.35234230, 0.00687490, 0.20204252, 0.07813186, 0.11081259, 0.04634665, 0.11073238, -0.01637954, 0.05104577,
+ 0.01675122, 0.01448696, 0.74013627, 0.06239059, 0.03129412, 0.08207461, 0.01249475, 0.02189238},
+{-1.27118948, 0.35834331, -0.33499347, 0.13524073, 0.04829079, 0.19542773, 0.05273835, 0.04157974, -0.01755227, 0.01513442,
+ 0.00386630, 0.02199463, 1.14439142, 0.21903073, 0.14750213, 0.12743356, 0.08463334, 0.06839691, -1.28367777, 0.35556287,
+-0.33809405, 0.13627881, 0.04939309, 0.19642571, 0.05354373, 0.04099247, -0.01787481, 0.01472425, 0.00391474, 0.02150716,
+ 1.14739079, 0.21840872, 0.14643624, 0.12724347, 0.08390642, 0.06811938, -1.29007667, 0.35159558, -0.34154267, 0.13295849,
+ 0.04883602, 0.19587595, 0.05452759, 0.04174703, -0.01782110, 0.01388270, 0.00374754, 0.02138105, 1.14333767, 0.21690116,
+ 0.14544599, 0.12606728, 0.08314168, 0.06771389, -1.29856471, 0.35239315, -0.34238732, 0.13277553, 0.04722712, 0.19233156,
+ 0.05366901, 0.04328110, -0.01657749, 0.01444736, 0.00438108, 0.02102563, 1.13548397, 0.21537812, 0.14357377, 0.12525845,
+ 0.08230994, 0.06722511, -1.30663540, 0.34366563, -0.34205544, 0.12861679, 0.04655851, 0.18864359, 0.05351285, 0.04358693,
+-0.01604498, 0.01431907, 0.00395326, 0.02082299, 1.12207794, 0.21167325, 0.14212491, 0.12418671, 0.08155467, 0.06639789,
+-1.31011673, 0.33686271, -0.34379843, 0.12169569, 0.04480323, 0.18637557, 0.05374078, 0.04260827, -0.01588226, 0.01378294,
+ 0.00396009, 0.02112406, 1.10466984, 0.20905894, 0.14107033, 0.12303074, 0.08047136, 0.06588031}};
+
diff --git a/src/mod/codecs/mod_isac/lpc_tables.h b/src/mod/codecs/mod_isac/lpc_tables.h
new file mode 100644
index 0000000000..604d963c37
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_tables.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * lpc_tables.h
+ *
+ * header file for coding tables for the LPC coefficients
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_
+
+#include "structs.h"
+
+#include "settings.h"
+
+#define KLT_STEPSIZE 1.00000000
+#define KLT_NUM_AVG_GAIN 0
+#define KLT_NUM_AVG_SHAPE 0
+#define KLT_NUM_MODELS 3
+#define LPC_GAIN_SCALE 4.000f
+#define LPC_LOBAND_SCALE 2.100f
+#define LPC_LOBAND_ORDER ORDERLO
+#define LPC_HIBAND_SCALE 0.450f
+#define LPC_HIBAND_ORDER ORDERHI
+#define LPC_GAIN_ORDER 2
+
+#define LPC_SHAPE_ORDER (LPC_LOBAND_ORDER + LPC_HIBAND_ORDER)
+
+#define KLT_ORDER_GAIN (LPC_GAIN_ORDER * SUBFRAMES)
+#define KLT_ORDER_SHAPE (LPC_SHAPE_ORDER * SUBFRAMES)
+/* indices of KLT coefficients used */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltSelIndGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltSelIndShape[108];
+
+/* cdf array for model indicator */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltModelCdf[KLT_NUM_MODELS+1];
+
+/* pointer to cdf array for model indicator */
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltModelCdfPtr[1];
+
+/* initial cdf index for decoder of model indicator */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltModelInitIndex[1];
+
+/* offset to go from rounded value to quantization index */
+extern const short WebRtcIsac_kQKltQuantMinGain[12];
+
+extern const short WebRtcIsac_kQKltQuantMinShape[108];
+
+/* maximum quantization index */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndGain[12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltMaxIndShape[108];
+
+/* index offset */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOffsetGain[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOffsetShape[KLT_NUM_MODELS][108];
+
+/* initial cdf index for KLT coefficients */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexGain[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltInitIndexShape[KLT_NUM_MODELS][108];
+
+/* offsets for quantizer representation levels */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOfLevelsGain[3];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltOfLevelsShape[3];
+
+/* quantizer representation levels */
+extern const double WebRtcIsac_kQKltLevelsGain[1176];
+
+extern const double WebRtcIsac_kQKltLevelsShape[1735];
+
+/* cdf tables for quantizer indices */
+extern const WebRtc_UWord16 WebRtcIsac_kQKltCdfGain[1212];
+
+extern const WebRtc_UWord16 WebRtcIsac_kQKltCdfShape[2059];
+
+/* pointers to cdf tables for quantizer indices */
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrGain[KLT_NUM_MODELS][12];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQKltCdfPtrShape[KLT_NUM_MODELS][108];
+
+/* code length for all coefficients using different models */
+extern const double WebRtcIsac_kQKltCodeLenGain[392];
+
+extern const double WebRtcIsac_kQKltCodeLenShape[578];
+
+/* left KLT transforms */
+extern const double WebRtcIsac_kKltT1Gain[KLT_NUM_MODELS][4];
+
+extern const double WebRtcIsac_kKltT1Shape[KLT_NUM_MODELS][324];
+
+/* right KLT transforms */
+extern const double WebRtcIsac_kKltT2Gain[KLT_NUM_MODELS][36];
+
+extern const double WebRtcIsac_kKltT2Shape[KLT_NUM_MODELS][36];
+
+/* means of log gains and LAR coefficients */
+extern const double WebRtcIsac_kLpcMeansGain[KLT_NUM_MODELS][12];
+
+extern const double WebRtcIsac_kLpcMeansShape[KLT_NUM_MODELS][108];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_TABLES_H_ */
diff --git a/src/mod/codecs/mod_isac/lpc_to_refl_coef.c b/src/mod/codecs/mod_isac/lpc_to_refl_coef.c
new file mode 100644
index 0000000000..2cb83c2e1d
--- /dev/null
+++ b/src/mod/codecs/mod_isac/lpc_to_refl_coef.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_LpcToReflCoef().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER 50
+
+void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* a16, int use_order, WebRtc_Word16* k16)
+{
+ int m, k;
+ WebRtc_Word32 tmp32[SPL_LPC_TO_REFL_COEF_MAX_AR_MODEL_ORDER];
+ WebRtc_Word32 tmp_inv_denom32;
+ WebRtc_Word16 tmp_inv_denom16;
+
+ k16[use_order - 1] = WEBRTC_SPL_LSHIFT_W16(a16[use_order], 3); //Q12<<3 => Q15
+ for (m = use_order - 1; m > 0; m--)
+ {
+ // (1 - k^2) in Q30
+ tmp_inv_denom32 = ((WebRtc_Word32)1073741823) - WEBRTC_SPL_MUL_16_16(k16[m], k16[m]);
+ // (1 - k^2) in Q15
+ tmp_inv_denom16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp_inv_denom32, 15);
+
+ for (k = 1; k <= m; k++)
+ {
+ // tmp[k] = (a[k] - RC[m] * a[m-k+1]) / (1.0 - RC[m]*RC[m]);
+
+ // [Q12<<16 - (Q15*Q12)<<1] = [Q28 - Q28] = Q28
+ tmp32[k] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)a16[k], 16)
+ - WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(k16[m], a16[m-k+1]), 1);
+
+ tmp32[k] = WebRtcSpl_DivW32W16(tmp32[k], tmp_inv_denom16); //Q28/Q15 = Q13
+ }
+
+ for (k = 1; k < m; k++)
+ {
+ a16[k] = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp32[k], 1); //Q13>>1 => Q12
+ }
+
+ tmp32[m] = WEBRTC_SPL_SAT(8191, tmp32[m], -8191);
+ k16[m - 1] = (WebRtc_Word16)WEBRTC_SPL_LSHIFT_W32(tmp32[m], 2); //Q13<<2 => Q15
+ }
+ return;
+}
diff --git a/src/mod/codecs/mod_isac/min_max_operations.c b/src/mod/codecs/mod_isac/min_max_operations.c
new file mode 100644
index 0000000000..57eaff7b71
--- /dev/null
+++ b/src/mod/codecs/mod_isac/min_max_operations.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This file contains the implementation of functions
+ * WebRtcSpl_MaxAbsValueW16()
+ * WebRtcSpl_MaxAbsIndexW16()
+ * WebRtcSpl_MaxAbsValueW32()
+ * WebRtcSpl_MaxValueW16()
+ * WebRtcSpl_MaxIndexW16()
+ * WebRtcSpl_MaxValueW32()
+ * WebRtcSpl_MaxIndexW32()
+ * WebRtcSpl_MinValueW16()
+ * WebRtcSpl_MinIndexW16()
+ * WebRtcSpl_MinValueW32()
+ * WebRtcSpl_MinIndexW32()
+ *
+ * The description header can be found in signal_processing_library.h.
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#if !(defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM_NEON))
+
+// Maximum absolute value of word16 vector.
+WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(const WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word32 tempMax = 0;
+ WebRtc_Word32 absVal;
+ WebRtc_Word16 totMax;
+ int i;
+ G_CONST WebRtc_Word16 *tmpvector = vector;
+
+ for (i = 0; i < length; i++)
+ {
+ absVal = WEBRTC_SPL_ABS_W32((*tmpvector));
+ if (absVal > tempMax)
+ {
+ tempMax = absVal;
+ }
+ tmpvector++;
+ }
+ totMax = (WebRtc_Word16)WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD16_MAX);
+ return totMax;
+}
+
+#endif
+
+// Index of maximum absolute value in a word16 vector.
+WebRtc_Word16 WebRtcSpl_MaxAbsIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 tempMax;
+ WebRtc_Word16 absTemp;
+ WebRtc_Word16 tempMaxIndex = 0;
+ WebRtc_Word16 i = 0;
+ G_CONST WebRtc_Word16 *tmpvector = vector;
+
+ tempMax = WEBRTC_SPL_ABS_W16(*tmpvector);
+ tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ absTemp = WEBRTC_SPL_ABS_W16(*tmpvector);
+ tmpvector++;
+ if (absTemp > tempMax)
+ {
+ tempMax = absTemp;
+ tempMaxIndex = i;
+ }
+ }
+ return tempMaxIndex;
+}
+
+// Maximum absolute value of word32 vector.
+WebRtc_Word32 WebRtcSpl_MaxAbsValueW32(G_CONST WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtc_UWord32 tempMax = 0;
+ WebRtc_UWord32 absVal;
+ WebRtc_Word32 retval;
+ int i;
+ G_CONST WebRtc_Word32 *tmpvector = vector;
+
+ for (i = 0; i < length; i++)
+ {
+ absVal = WEBRTC_SPL_ABS_W32((*tmpvector));
+ if (absVal > tempMax)
+ {
+ tempMax = absVal;
+ }
+ tmpvector++;
+ }
+ retval = (WebRtc_Word32)(WEBRTC_SPL_MIN(tempMax, WEBRTC_SPL_WORD32_MAX));
+ return retval;
+}
+
+// Maximum value of word16 vector.
+#ifndef XSCALE_OPT
+WebRtc_Word16 WebRtcSpl_MaxValueW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 tempMax;
+ WebRtc_Word16 i;
+ G_CONST WebRtc_Word16 *tmpvector = vector;
+
+ tempMax = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ > tempMax)
+ tempMax = vector[i];
+ }
+ return tempMax;
+}
+#else
+#pragma message(">> WebRtcSpl_MaxValueW16 is excluded from this build")
+#endif
+
+// Index of maximum value in a word16 vector.
+WebRtc_Word16 WebRtcSpl_MaxIndexW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 tempMax;
+ WebRtc_Word16 tempMaxIndex = 0;
+ WebRtc_Word16 i = 0;
+ G_CONST WebRtc_Word16 *tmpvector = vector;
+
+ tempMax = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ > tempMax)
+ {
+ tempMax = vector[i];
+ tempMaxIndex = i;
+ }
+ }
+ return tempMaxIndex;
+}
+
+// Maximum value of word32 vector.
+#ifndef XSCALE_OPT
+WebRtc_Word32 WebRtcSpl_MaxValueW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word32 tempMax;
+ WebRtc_Word16 i;
+ G_CONST WebRtc_Word32 *tmpvector = vector;
+
+ tempMax = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ > tempMax)
+ tempMax = vector[i];
+ }
+ return tempMax;
+}
+#else
+#pragma message(">> WebRtcSpl_MaxValueW32 is excluded from this build")
+#endif
+
+// Index of maximum value in a word32 vector.
+WebRtc_Word16 WebRtcSpl_MaxIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word32 tempMax;
+ WebRtc_Word16 tempMaxIndex = 0;
+ WebRtc_Word16 i = 0;
+ G_CONST WebRtc_Word32 *tmpvector = vector;
+
+ tempMax = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ > tempMax)
+ {
+ tempMax = vector[i];
+ tempMaxIndex = i;
+ }
+ }
+ return tempMaxIndex;
+}
+
+// Minimum value of word16 vector.
+WebRtc_Word16 WebRtcSpl_MinValueW16(G_CONST WebRtc_Word16 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 tempMin;
+ WebRtc_Word16 i;
+ G_CONST WebRtc_Word16 *tmpvector = vector;
+
+ // Find the minimum value
+ tempMin = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ < tempMin)
+ tempMin = (vector[i]);
+ }
+ return tempMin;
+}
+
+// Index of minimum value in a word16 vector.
+#ifndef XSCALE_OPT
+WebRtc_Word16 WebRtcSpl_MinIndexW16(G_CONST WebRtc_Word16* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word16 tempMin;
+ WebRtc_Word16 tempMinIndex = 0;
+ WebRtc_Word16 i = 0;
+ G_CONST WebRtc_Word16* tmpvector = vector;
+
+ // Find index of smallest value
+ tempMin = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ < tempMin)
+ {
+ tempMin = vector[i];
+ tempMinIndex = i;
+ }
+ }
+ return tempMinIndex;
+}
+#else
+#pragma message(">> WebRtcSpl_MinIndexW16 is excluded from this build")
+#endif
+
+// Minimum value of word32 vector.
+WebRtc_Word32 WebRtcSpl_MinValueW32(G_CONST WebRtc_Word32 *vector, WebRtc_Word16 length)
+{
+ WebRtc_Word32 tempMin;
+ WebRtc_Word16 i;
+ G_CONST WebRtc_Word32 *tmpvector = vector;
+
+ // Find the minimum value
+ tempMin = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ < tempMin)
+ tempMin = (vector[i]);
+ }
+ return tempMin;
+}
+
+// Index of minimum value in a word32 vector.
+#ifndef XSCALE_OPT
+WebRtc_Word16 WebRtcSpl_MinIndexW32(G_CONST WebRtc_Word32* vector, WebRtc_Word16 length)
+{
+ WebRtc_Word32 tempMin;
+ WebRtc_Word16 tempMinIndex = 0;
+ WebRtc_Word16 i = 0;
+ G_CONST WebRtc_Word32 *tmpvector = vector;
+
+ // Find index of smallest value
+ tempMin = *tmpvector++;
+ for (i = 1; i < length; i++)
+ {
+ if (*tmpvector++ < tempMin)
+ {
+ tempMin = vector[i];
+ tempMinIndex = i;
+ }
+ }
+ return tempMinIndex;
+}
+#else
+#pragma message(">> WebRtcSpl_MinIndexW32 is excluded from this build")
+#endif
diff --git a/src/mod/codecs/mod_isac/min_max_operations_neon.c b/src/mod/codecs/mod_isac/min_max_operations_neon.c
new file mode 100644
index 0000000000..158bcc1837
--- /dev/null
+++ b/src/mod/codecs/mod_isac/min_max_operations_neon.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#if (defined(WEBRTC_ANDROID) && defined(WEBRTC_ARCH_ARM_NEON))
+
+#include
+
+#include "signal_processing_library.h"
+
+// Maximum absolute value of word16 vector.
+WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(const WebRtc_Word16* vector,
+ WebRtc_Word16 length) {
+ WebRtc_Word32 temp_max = 0;
+ WebRtc_Word32 abs_val;
+ WebRtc_Word16 tot_max;
+ int i;
+
+ __asm__("vmov.i16 d25, #0" : : : "d25");
+
+ for (i = 0; i < length - 7; i += 8) {
+ __asm__("vld1.16 {d26, d27}, [%0]" : : "r"(&vector[i]) : "q13");
+ __asm__("vabs.s16 q13, q13" : : : "q13");
+ __asm__("vpmax.s16 d26, d27" : : : "q13");
+ __asm__("vpmax.s16 d25, d26" : : : "d25", "d26");
+ }
+ __asm__("vpmax.s16 d25, d25" : : : "d25");
+ __asm__("vpmax.s16 d25, d25" : : : "d25");
+ __asm__("vmov.s16 %0, d25[0]" : "=r"(temp_max): : "d25");
+
+ for (; i < length; i++) {
+ abs_val = WEBRTC_SPL_ABS_W32((vector[i]));
+ if (abs_val > temp_max) {
+ temp_max = abs_val;
+ }
+ }
+ tot_max = (WebRtc_Word16)WEBRTC_SPL_MIN(temp_max, WEBRTC_SPL_WORD16_MAX);
+ return tot_max;
+}
+
+#endif
diff --git a/src/mod/codecs/mod_isac/mod_iSAC.2008.vcproj b/src/mod/codecs/mod_isac/mod_iSAC.2008.vcproj
new file mode 100644
index 0000000000..e10f663275
--- /dev/null
+++ b/src/mod/codecs/mod_isac/mod_iSAC.2008.vcproj
@@ -0,0 +1,643 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mod/codecs/mod_isac/mod_iSAC.2010.vcxproj b/src/mod/codecs/mod_isac/mod_iSAC.2010.vcxproj
new file mode 100644
index 0000000000..369cd51a67
--- /dev/null
+++ b/src/mod/codecs/mod_isac/mod_iSAC.2010.vcxproj
@@ -0,0 +1,222 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ mod_iSAC
+ {7F1610F1-DD5A-4CF7-8610-30AB12C60ADD}
+ mod_iSAC
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ X64
+
+
+
+
+
+
+ false
+
+
+ MachineX64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {202d7a4e-760d-4d0e-afa1-d7459ced30ff}
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/mod/codecs/mod_isac/mod_isac.c b/src/mod/codecs/mod_isac/mod_isac.c
new file mode 100644
index 0000000000..3f5f40aadb
--- /dev/null
+++ b/src/mod/codecs/mod_isac/mod_isac.c
@@ -0,0 +1,257 @@
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2011, Anthony Minessale II
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / ISAC codec module
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Anthony Minessale II
+ *
+ *
+ * mod_isac.c -- isac Codec Module
+ *
+ */
+
+#include
+#include "isac.h"
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_isac_codec_load);
+SWITCH_MODULE_DEFINITION(mod_isac, mod_isac_codec_load, NULL, NULL);
+
+struct isac_context {
+ ISACStruct *ISAC_main_inst;
+};
+
+static switch_status_t switch_isac_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
+{
+ uint32_t encoding, decoding;
+ WebRtc_Word16 err;
+ struct isac_context *context = NULL;
+
+ encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
+ decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
+
+ if (!(encoding || decoding)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context)))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ codec->private_info = context;
+
+ err = WebRtcIsac_Create(&context->ISAC_main_inst);
+
+ if (err < 0) return SWITCH_STATUS_FALSE;
+
+ WebRtcIsac_SetEncSampRate(context->ISAC_main_inst, codec->implementation->actual_samples_per_second / 1000);
+ WebRtcIsac_SetDecSampRate(context->ISAC_main_inst, codec->implementation->actual_samples_per_second / 1000);
+
+ if (encoding) {
+ if (WebRtcIsac_EncoderInit(context->ISAC_main_inst, 0) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ if (decoding) {
+ if (WebRtcIsac_DecoderInit(context->ISAC_main_inst) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ if (codec->implementation->actual_samples_per_second == 16000) {
+ if (WebRtcIsac_ControlBwe(context->ISAC_main_inst, 0, codec->implementation->microseconds_per_packet / 1000, 0) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+ } else {
+ if (WebRtcIsac_Control(context->ISAC_main_inst, codec->implementation->actual_samples_per_second / 1000,
+ codec->implementation->microseconds_per_packet / 1000) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ if (WebRtcIsac_SetMaxPayloadSize(context->ISAC_main_inst, SWITCH_RECOMMENDED_BUFFER_SIZE) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (WebRtcIsac_SetMaxRate(context->ISAC_main_inst, codec->implementation->bits_per_second) < 0) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_isac_encode(switch_codec_t *codec, switch_codec_t *other_codec,
+ void *decoded_data,
+ uint32_t decoded_data_len,
+ uint32_t decoded_rate,
+ void *encoded_data,
+ uint32_t *encoded_data_len,
+ uint32_t *encoded_rate,
+ unsigned int *flag)
+{
+ struct isac_context *context = codec->private_info;
+ WebRtc_Word16 len = 0, *in, *out;
+ int rise = (codec->implementation->actual_samples_per_second / 100);
+
+ in = decoded_data;
+ out = encoded_data;
+
+ while(len == 0) {
+ len = WebRtcIsac_Encode(context->ISAC_main_inst, in, out);
+ in += rise;
+ }
+
+ if (len < 0) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ *encoded_data_len = (uint32_t) len;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_isac_decode(switch_codec_t *codec,
+ switch_codec_t *other_codec,
+ void *encoded_data,
+ uint32_t encoded_data_len,
+ uint32_t encoded_rate,
+ void *decoded_data,
+ uint32_t *decoded_data_len,
+ uint32_t *decoded_rate,
+ unsigned int *flag)
+{
+ struct isac_context *context = codec->private_info;
+ WebRtc_Word16 len, speechType[1];
+
+ if ((*flag & SFF_PLC)) {
+ len = WebRtcIsac_DecodePlc(context->ISAC_main_inst, decoded_data, 1);
+ } else {
+ len = WebRtcIsac_Decode(context->ISAC_main_inst, encoded_data, encoded_data_len, decoded_data, speechType);
+ }
+
+ if (len < 0) {
+ *decoded_data_len = 0;
+ return SWITCH_STATUS_GENERR;
+ }
+
+ *decoded_data_len = (uint32_t) len * 2;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t switch_isac_destroy(switch_codec_t *codec)
+{
+ struct isac_context *context = codec->private_info;
+
+ WebRtcIsac_Free(context->ISAC_main_inst);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_isac_codec_load)
+{
+ switch_codec_interface_t *codec_interface;
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+ SWITCH_ADD_CODEC(codec_interface, "isac"); /* 8.0kbit */
+
+ switch_core_codec_add_implementation(pool, codec_interface,
+ SWITCH_CODEC_TYPE_AUDIO,
+ 99,
+ "isac",
+ NULL,
+ 16000,
+ 16000,
+ 53400,
+ 30000,
+ 480,
+ 960,
+ 0,
+ 1,
+ 3,
+ switch_isac_init,
+ switch_isac_encode,
+ switch_isac_decode,
+ switch_isac_destroy);
+
+
+
+ switch_core_codec_add_implementation(pool, codec_interface,
+ SWITCH_CODEC_TYPE_AUDIO,
+ 99,
+ "isac",
+ NULL,
+ 16000,
+ 16000,
+ 53400,
+ 60000,
+ 960,
+ 1920,
+ 0,
+ 1,
+ 6,
+ switch_isac_init,
+ switch_isac_encode,
+ switch_isac_decode,
+ switch_isac_destroy);
+
+
+
+
+ switch_core_codec_add_implementation(pool, codec_interface,
+ SWITCH_CODEC_TYPE_AUDIO,
+ 99,
+ "isac",
+ NULL,
+ 32000,
+ 32000,
+ 160000,
+ 30000,
+ 960,
+ 1920,
+ 0,
+ 1,
+ 6,
+ switch_isac_init,
+ switch_isac_encode,
+ switch_isac_decode,
+ switch_isac_destroy);
+
+
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
diff --git a/src/mod/codecs/mod_isac/os_specific_inline.h b/src/mod/codecs/mod_isac/os_specific_inline.h
new file mode 100644
index 0000000000..c469c2ec9c
--- /dev/null
+++ b/src/mod/codecs/mod_isac/os_specific_inline.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
+
+#include
+#include "typedefs.h"
+
+// TODO(turaj): switch to WEBRTC_POSIX when available
+#if defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
+#define WebRtcIsac_lrint lrint
+#elif (defined(WEBRTC_ARCH_X86) && defined(WIN32))
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+
+ __asm {
+ fld x_dbl
+ fistp x_int
+ };
+
+ return x_int;
+}
+#else // Do a slow but correct implementation of lrint
+
+static __inline long int WebRtcIsac_lrint(double x_dbl) {
+ long int x_int;
+ x_int = (long int)floor(x_dbl + 0.499999999999);
+ return x_int;
+}
+
+#endif
+
+#endif // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
diff --git a/src/mod/codecs/mod_isac/pitch_estimator.c b/src/mod/codecs/mod_isac/pitch_estimator.c
new file mode 100644
index 0000000000..75525f69d4
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_estimator.c
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_estimator.h"
+
+#include
+#include
+#ifdef WEBRTC_ANDROID
+#include
+#endif
+
+static const double kInterpolWin[8] = {-0.00067556028640, 0.02184247643159, -0.12203175715679, 0.60086484101160,
+ 0.60086484101160, -0.12203175715679, 0.02184247643159, -0.00067556028640};
+
+/* interpolation filter */
+__inline static void IntrepolFilter(double *data_ptr, double *intrp)
+{
+ *intrp = kInterpolWin[0] * data_ptr[-3];
+ *intrp += kInterpolWin[1] * data_ptr[-2];
+ *intrp += kInterpolWin[2] * data_ptr[-1];
+ *intrp += kInterpolWin[3] * data_ptr[0];
+ *intrp += kInterpolWin[4] * data_ptr[1];
+ *intrp += kInterpolWin[5] * data_ptr[2];
+ *intrp += kInterpolWin[6] * data_ptr[3];
+ *intrp += kInterpolWin[7] * data_ptr[4];
+}
+
+
+/* 2D parabolic interpolation */
+/* probably some 0.5 factors can be eliminated, and the square-roots can be removed from the Cholesky fact. */
+__inline static void Intrpol2D(double T[3][3], double *x, double *y, double *peak_val)
+{
+ double c, b[2], A[2][2];
+ double t1, t2, d;
+ double delta1, delta2;
+
+
+ // double T[3][3] = {{-1.25, -.25,-.25}, {-.25, .75, .75}, {-.25, .75, .75}};
+ // should result in: delta1 = 0.5; delta2 = 0.0; peak_val = 1.0
+
+ c = T[1][1];
+ b[0] = 0.5 * (T[1][2] + T[2][1] - T[0][1] - T[1][0]);
+ b[1] = 0.5 * (T[1][0] + T[2][1] - T[0][1] - T[1][2]);
+ A[0][1] = -0.5 * (T[0][1] + T[2][1] - T[1][0] - T[1][2]);
+ t1 = 0.5 * (T[0][0] + T[2][2]) - c;
+ t2 = 0.5 * (T[2][0] + T[0][2]) - c;
+ d = (T[0][1] + T[1][2] + T[1][0] + T[2][1]) - 4.0 * c - t1 - t2;
+ A[0][0] = -t1 - 0.5 * d;
+ A[1][1] = -t2 - 0.5 * d;
+
+ /* deal with singularities or ill-conditioned cases */
+ if ( (A[0][0] < 1e-7) || ((A[0][0] * A[1][1] - A[0][1] * A[0][1]) < 1e-7) ) {
+ *peak_val = T[1][1];
+ return;
+ }
+
+ /* Cholesky decomposition: replace A by upper-triangular factor */
+ A[0][0] = sqrt(A[0][0]);
+ A[0][1] = A[0][1] / A[0][0];
+ A[1][1] = sqrt(A[1][1] - A[0][1] * A[0][1]);
+
+ /* compute [x; y] = -0.5 * inv(A) * b */
+ t1 = b[0] / A[0][0];
+ t2 = (b[1] - t1 * A[0][1]) / A[1][1];
+ delta2 = t2 / A[1][1];
+ delta1 = 0.5 * (t1 - delta2 * A[0][1]) / A[0][0];
+ delta2 *= 0.5;
+
+ /* limit norm */
+ t1 = delta1 * delta1 + delta2 * delta2;
+ if (t1 > 1.0) {
+ delta1 /= t1;
+ delta2 /= t1;
+ }
+
+ *peak_val = 0.5 * (b[0] * delta1 + b[1] * delta2) + c;
+
+ *x += delta1;
+ *y += delta2;
+}
+
+
+static void PCorr(const double *in, double *outcorr)
+{
+ double sum, ysum, prod;
+ const double *x, *inptr;
+ int k, n;
+
+ //ysum = 1e-6; /* use this with float (i.s.o. double)! */
+ ysum = 1e-13;
+ sum = 0.0;
+ x = in + PITCH_MAX_LAG/2 + 2;
+ for (n = 0; n < PITCH_CORR_LEN2; n++) {
+ ysum += in[n] * in[n];
+ sum += x[n] * in[n];
+ }
+
+ outcorr += PITCH_LAG_SPAN2 - 1; /* index of last element in array */
+ *outcorr = sum / sqrt(ysum);
+
+ for (k = 1; k < PITCH_LAG_SPAN2; k++) {
+ ysum -= in[k-1] * in[k-1];
+ ysum += in[PITCH_CORR_LEN2 + k - 1] * in[PITCH_CORR_LEN2 + k - 1];
+ sum = 0.0;
+ inptr = &in[k];
+ prod = x[0] * inptr[0];
+ for (n = 1; n < PITCH_CORR_LEN2; n++) {
+ sum += prod;
+ prod = x[n] * inptr[n];
+ }
+ sum += prod;
+ outcorr--;
+ *outcorr = sum / sqrt(ysum);
+ }
+}
+
+
+void WebRtcIsac_InitializePitch(const double *in,
+ const double old_lag,
+ const double old_gain,
+ PitchAnalysisStruct *State,
+ double *lags)
+{
+ double buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2];
+ double ratio, log_lag, gain_bias;
+ double bias;
+ double corrvec1[PITCH_LAG_SPAN2];
+ double corrvec2[PITCH_LAG_SPAN2];
+ int m, k;
+ // Allocating 10 extra entries at the begining of the CorrSurf
+ double corrSurfBuff[10 + (2*PITCH_BW+3)*(PITCH_LAG_SPAN2+4)];
+ double* CorrSurf[2*PITCH_BW+3];
+ double *CorrSurfPtr1, *CorrSurfPtr2;
+ double LagWin[3] = {0.2, 0.5, 0.98};
+ int ind1, ind2, peaks_ind, peak, max_ind;
+ int peaks[PITCH_MAX_NUM_PEAKS];
+ double adj, gain_tmp;
+ double corr, corr_max;
+ double intrp_a, intrp_b, intrp_c, intrp_d;
+ double peak_vals[PITCH_MAX_NUM_PEAKS];
+ double lags1[PITCH_MAX_NUM_PEAKS];
+ double lags2[PITCH_MAX_NUM_PEAKS];
+ double T[3][3];
+ int row;
+
+ for(k = 0; k < 2*PITCH_BW+3; k++)
+ {
+ CorrSurf[k] = &corrSurfBuff[10 + k * (PITCH_LAG_SPAN2+4)];
+ }
+ /* reset CorrSurf matrix */
+ memset(corrSurfBuff, 0, sizeof(double) * (10 + (2*PITCH_BW+3) * (PITCH_LAG_SPAN2+4)));
+
+ //warnings -DH
+ max_ind = 0;
+ peak = 0;
+
+ /* copy old values from state buffer */
+ memcpy(buf_dec, State->dec_buffer, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* decimation; put result after the old values */
+ WebRtcIsac_DecimateAllpass(in, State->decimator_state, PITCH_FRAME_LEN,
+ &buf_dec[PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2]);
+
+ /* low-pass filtering */
+ for (k = PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2; k < PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2+2; k++)
+ buf_dec[k] += 0.75 * buf_dec[k-1] - 0.25 * buf_dec[k-2];
+
+ /* copy end part back into state buffer */
+ memcpy(State->dec_buffer, buf_dec+PITCH_FRAME_LEN/2, sizeof(double) * (PITCH_CORR_LEN2+PITCH_CORR_STEP2+PITCH_MAX_LAG/2-PITCH_FRAME_LEN/2+2));
+
+ /* compute correlation for first and second half of the frame */
+ PCorr(buf_dec, corrvec1);
+ PCorr(buf_dec + PITCH_CORR_STEP2, corrvec2);
+
+ /* bias towards pitch lag of previous frame */
+ log_lag = log(0.5 * old_lag);
+ gain_bias = 4.0 * old_gain * old_gain;
+ if (gain_bias > 0.8) gain_bias = 0.8;
+ for (k = 0; k < PITCH_LAG_SPAN2; k++)
+ {
+ ratio = log((double) (k + (PITCH_MIN_LAG/2-2))) - log_lag;
+ bias = 1.0 + gain_bias * exp(-5.0 * ratio * ratio);
+ corrvec1[k] *= bias;
+ }
+
+ /* taper correlation functions */
+ for (k = 0; k < 3; k++) {
+ gain_tmp = LagWin[k];
+ corrvec1[k] *= gain_tmp;
+ corrvec2[k] *= gain_tmp;
+ corrvec1[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ corrvec2[PITCH_LAG_SPAN2-1-k] *= gain_tmp;
+ }
+
+ corr_max = 0.0;
+ /* fill middle row of correlation surface */
+ ind1 = 0;
+ ind2 = 0;
+ CorrSurfPtr1 = &CorrSurf[PITCH_BW][2];
+ for (k = 0; k < PITCH_LAG_SPAN2; k++) {
+ corr = corrvec1[ind1++] + corrvec2[ind2++];
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill first and last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW;
+ CorrSurfPtr1 = &CorrSurf[0][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW][PITCH_BW+2];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.2 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill second and next to last rows of correlation surface */
+ ind1 = 0;
+ ind2 = PITCH_BW-1;
+ CorrSurfPtr1 = &CorrSurf[1][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-1][PITCH_BW+1];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+1; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = 0.9 * ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ /* fill remainder of correlation surface */
+ for (m = 2; m < PITCH_BW; m++) {
+ ind1 = 0;
+ ind2 = PITCH_BW - m; /* always larger than ind1 */
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ CorrSurfPtr2 = &CorrSurf[2*PITCH_BW-m][PITCH_BW+2-m];
+ for (k = 0; k < PITCH_LAG_SPAN2-PITCH_BW+m; k++) {
+ ratio = ((double) (ind1 + 12)) / ((double) (ind2 + 12));
+ adj = ratio * (2.0 - ratio); /* adjustment factor; inverse parabola as a function of ratio */
+ corr = adj * (corrvec1[ind1] + corrvec2[ind2]);
+ CorrSurfPtr1[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ }
+ corr = adj * (corrvec1[ind2++] + corrvec2[ind1++]);
+ CorrSurfPtr2[k] = corr;
+ if (corr > corr_max) {
+ corr_max = corr; /* update maximum */
+ max_ind = (int)(&CorrSurfPtr2[k] - &CorrSurf[0][0]);
+ }
+ }
+ }
+
+ /* threshold value to qualify as a peak */
+ corr_max *= 0.6;
+
+ peaks_ind = 0;
+ /* find peaks */
+ for (m = 1; m < PITCH_BW+1; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2; k < PITCH_LAG_SPAN2-PITCH_BW-2+m; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+ for (m = PITCH_BW+1; m < 2*PITCH_BW; m++) {
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ CorrSurfPtr1 = &CorrSurf[m][2];
+ for (k = 2+m-PITCH_BW; k < PITCH_LAG_SPAN2-2; k++) {
+ corr = CorrSurfPtr1[k];
+ if (corr > corr_max) {
+ if ( (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+5)]) && (corr > CorrSurfPtr1[k - (PITCH_LAG_SPAN2+4)]) ) {
+ if ( (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+4)]) && (corr > CorrSurfPtr1[k + (PITCH_LAG_SPAN2+5)]) ) {
+ /* found a peak; store index into matrix */
+ peaks[peaks_ind++] = (int)(&CorrSurfPtr1[k] - &CorrSurf[0][0]);
+ if (peaks_ind == PITCH_MAX_NUM_PEAKS) break;
+ }
+ }
+ }
+ }
+ }
+
+ if (peaks_ind > 0) {
+ /* examine each peak */
+ CorrSurfPtr1 = &CorrSurf[0][0];
+ for (k = 0; k < peaks_ind; k++) {
+ peak = peaks[k];
+
+ /* compute four interpolated values around current peak */
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)], &intrp_a);
+ IntrepolFilter(&CorrSurfPtr1[peak - 1 ], &intrp_b);
+ IntrepolFilter(&CorrSurfPtr1[peak ], &intrp_c);
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)], &intrp_d);
+
+ /* determine maximum of the interpolated values */
+ corr = CorrSurfPtr1[peak];
+ corr_max = intrp_a;
+ if (intrp_b > corr_max) corr_max = intrp_b;
+ if (intrp_c > corr_max) corr_max = intrp_c;
+ if (intrp_d > corr_max) corr_max = intrp_d;
+
+ /* determine where the peak sits and fill a 3x3 matrix around it */
+ row = peak / (PITCH_LAG_SPAN2+4);
+ lags1[k] = (double) ((peak - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[k] = (double) (lags1[k] + PITCH_BW - row);
+ if ( corr > corr_max ) {
+ T[0][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][1] = corr;
+ T[0][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][0] = intrp_a;
+ T[0][1] = intrp_b;
+ T[2][1] = intrp_c;
+ T[1][2] = intrp_d;
+ } else {
+ if (intrp_a == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] += 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - 2*(PITCH_LAG_SPAN2+5)], &T[0][0]);
+ IntrepolFilter(&CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)], &T[2][0]);
+ T[1][1] = intrp_a;
+ T[0][2] = intrp_b;
+ T[2][2] = intrp_c;
+ T[1][0] = CorrSurfPtr1[peak - (2*PITCH_LAG_SPAN2+9)];
+ T[0][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[2][1] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[1][2] = corr;
+ } else if (intrp_b == corr_max) {
+ lags1[k] -= 0.5;
+ lags2[k] -= 0.5;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+6)], &T[0][0]);
+ T[2][0] = intrp_a;
+ T[1][1] = intrp_b;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+3)], &T[0][2]);
+ T[2][2] = intrp_d;
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+5)];
+ T[0][1] = CorrSurfPtr1[peak - 1];
+ T[2][1] = corr;
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ } else if (intrp_c == corr_max) {
+ lags1[k] += 0.5;
+ lags2[k] += 0.5;
+ T[0][0] = intrp_a;
+ IntrepolFilter(&CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)], &T[2][0]);
+ T[1][1] = intrp_c;
+ T[0][2] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)], &T[2][2]);
+ T[1][0] = CorrSurfPtr1[peak - (PITCH_LAG_SPAN2+4)];
+ T[0][1] = corr;
+ T[2][1] = CorrSurfPtr1[peak + 1];
+ T[1][2] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ } else {
+ lags1[k] += 0.5;
+ lags2[k] -= 0.5;
+ T[0][0] = intrp_b;
+ T[2][0] = intrp_c;
+ T[1][1] = intrp_d;
+ IntrepolFilter(&CorrSurfPtr1[peak + 2*(PITCH_LAG_SPAN2+4)], &T[0][2]);
+ IntrepolFilter(&CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)], &T[2][2]);
+ T[1][0] = corr;
+ T[0][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+4)];
+ T[2][1] = CorrSurfPtr1[peak + (PITCH_LAG_SPAN2+5)];
+ T[1][2] = CorrSurfPtr1[peak + (2*PITCH_LAG_SPAN2+9)];
+ }
+ }
+
+ /* 2D parabolic interpolation gives more accurate lags and peak value */
+ Intrpol2D(T, &lags1[k], &lags2[k], &peak_vals[k]);
+ }
+
+ /* determine the highest peak, after applying a bias towards short lags */
+ corr_max = 0.0;
+ for (k = 0; k < peaks_ind; k++) {
+ corr = peak_vals[k] * pow(PITCH_PEAK_DECAY, log(lags1[k] + lags2[k]));
+ if (corr > corr_max) {
+ corr_max = corr;
+ peak = k;
+ }
+ }
+
+ lags1[peak] *= 2.0;
+ lags2[peak] *= 2.0;
+
+ if (lags1[peak] < (double) PITCH_MIN_LAG) lags1[peak] = (double) PITCH_MIN_LAG;
+ if (lags2[peak] < (double) PITCH_MIN_LAG) lags2[peak] = (double) PITCH_MIN_LAG;
+ if (lags1[peak] > (double) PITCH_MAX_LAG) lags1[peak] = (double) PITCH_MAX_LAG;
+ if (lags2[peak] > (double) PITCH_MAX_LAG) lags2[peak] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[peak];
+ lags[1] = lags1[peak];
+ lags[2] = lags2[peak];
+ lags[3] = lags2[peak];
+ }
+ else
+ {
+ row = max_ind / (PITCH_LAG_SPAN2+4);
+ lags1[0] = (double) ((max_ind - row * (PITCH_LAG_SPAN2+4)) + PITCH_MIN_LAG/2 - 4);
+ lags2[0] = (double) (lags1[0] + PITCH_BW - row);
+
+ if (lags1[0] < (double) PITCH_MIN_LAG) lags1[0] = (double) PITCH_MIN_LAG;
+ if (lags2[0] < (double) PITCH_MIN_LAG) lags2[0] = (double) PITCH_MIN_LAG;
+ if (lags1[0] > (double) PITCH_MAX_LAG) lags1[0] = (double) PITCH_MAX_LAG;
+ if (lags2[0] > (double) PITCH_MAX_LAG) lags2[0] = (double) PITCH_MAX_LAG;
+
+ /* store lags of highest peak in output array */
+ lags[0] = lags1[0];
+ lags[1] = lags1[0];
+ lags[2] = lags2[0];
+ lags[3] = lags2[0];
+ }
+}
+
+
+
+/* create weighting matrix by orthogonalizing a basis of polynomials of increasing order
+ * t = (0:4)';
+ * A = [t.^0, t.^1, t.^2, t.^3, t.^4];
+ * [Q, dummy] = qr(A);
+ * P.Weight = Q * diag([0, .1, .5, 1, 1]) * Q'; */
+static const double kWeight[5][5] = {
+ { 0.29714285714286, -0.30857142857143, -0.05714285714286, 0.05142857142857, 0.01714285714286},
+ {-0.30857142857143, 0.67428571428571, -0.27142857142857, -0.14571428571429, 0.05142857142857},
+ {-0.05714285714286, -0.27142857142857, 0.65714285714286, -0.27142857142857, -0.05714285714286},
+ { 0.05142857142857, -0.14571428571429, -0.27142857142857, 0.67428571428571, -0.30857142857143},
+ { 0.01714285714286, 0.05142857142857, -0.05714285714286, -0.30857142857143, 0.29714285714286}
+};
+
+
+void WebRtcIsac_PitchAnalysis(const double *in, /* PITCH_FRAME_LEN samples */
+ double *out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ double *lags,
+ double *gains)
+{
+ double HPin[PITCH_FRAME_LEN];
+ double Weighted[PITCH_FRAME_LEN];
+ double Whitened[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double inbuf[PITCH_FRAME_LEN + QLOOKAHEAD];
+ double out_G[PITCH_FRAME_LEN + QLOOKAHEAD]; // could be removed by using out instead
+ double out_dG[4][PITCH_FRAME_LEN + QLOOKAHEAD];
+ double old_lag, old_gain;
+ double nrg_wht, tmp;
+ double Wnrg, Wfluct, Wgain;
+ double H[4][4];
+ double grad[4];
+ double dG[4];
+ int k, m, n, iter;
+
+ /* high pass filtering using second order pole-zero filter */
+ WebRtcIsac_Highpass(in, HPin, State->hp_state, PITCH_FRAME_LEN);
+
+ /* copy from state into buffer */
+ memcpy(Whitened, State->whitened_buf, sizeof(double) * QLOOKAHEAD);
+
+ /* compute weighted and whitened signals */
+ WebRtcIsac_WeightingFilter(HPin, &Weighted[0], &Whitened[QLOOKAHEAD], &(State->Wghtstr));
+
+ /* copy from buffer into state */
+ memcpy(State->whitened_buf, Whitened+PITCH_FRAME_LEN, sizeof(double) * QLOOKAHEAD);
+
+ old_lag = State->PFstr_wght.oldlagp[0];
+ old_gain = State->PFstr_wght.oldgainp[0];
+
+ /* inital pitch estimate */
+ WebRtcIsac_InitializePitch(Weighted, old_lag, old_gain, State, lags);
+
+
+ /* Iterative optimization of lags - to be done */
+
+ /* compute energy of whitened signal */
+ nrg_wht = 0.0;
+ for (k = 0; k < PITCH_FRAME_LEN + QLOOKAHEAD; k++)
+ nrg_wht += Whitened[k] * Whitened[k];
+
+
+ /* Iterative optimization of gains */
+
+ /* set weights for energy, gain fluctiation, and spectral gain penalty functions */
+ Wnrg = 1.0 / nrg_wht;
+ Wgain = 0.005;
+ Wfluct = 3.0;
+
+ /* set initial gains */
+ for (k = 0; k < 4; k++)
+ gains[k] = PITCH_MAX_GAIN_06;
+
+ /* two iterations should be enough */
+ for (iter = 0; iter < 2; iter++) {
+ /* compute Jacobian of pre-filter output towards gains */
+ WebRtcIsac_PitchfilterPre_gains(Whitened, out_G, out_dG, &(State->PFstr_wght), lags, gains);
+
+ /* gradient and approximate Hessian (lower triangle) for minimizing the filter's output power */
+ for (k = 0; k < 4; k++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_G[n] * out_dG[k][n];
+ grad[k] = tmp * Wnrg;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ tmp = 0.0;
+ for (n = 0; n < PITCH_FRAME_LEN + QLOOKAHEAD; n++)
+ tmp += out_dG[m][n] * out_dG[k][n];
+ H[k][m] = tmp * Wnrg;
+ }
+ }
+
+ /* add gradient and Hessian (lower triangle) for dampening fast gain changes */
+ for (k = 0; k < 4; k++) {
+ tmp = kWeight[k+1][0] * old_gain;
+ for (m = 0; m < 4; m++)
+ tmp += kWeight[k+1][m+1] * gains[m];
+ grad[k] += tmp * Wfluct;
+ }
+ for (k = 0; k < 4; k++) {
+ for (m = 0; m <= k; m++) {
+ H[k][m] += kWeight[k+1][m+1] * Wfluct;
+ }
+ }
+
+ /* add gradient and Hessian for dampening gain */
+ for (k = 0; k < 3; k++) {
+ tmp = 1.0 / (1 - gains[k]);
+ grad[k] += tmp * tmp * Wgain;
+ H[k][k] += 2.0 * tmp * (tmp * tmp * Wgain);
+ }
+ tmp = 1.0 / (1 - gains[3]);
+ grad[3] += 1.33 * (tmp * tmp * Wgain);
+ H[3][3] += 2.66 * tmp * (tmp * tmp * Wgain);
+
+
+ /* compute Cholesky factorization of Hessian
+ * by overwritting the upper triangle; scale factors on diagonal
+ * (for non pc-platforms store the inverse of the diagonals seperately to minimize divisions) */
+ H[0][1] = H[1][0] / H[0][0];
+ H[0][2] = H[2][0] / H[0][0];
+ H[0][3] = H[3][0] / H[0][0];
+ H[1][1] -= H[0][0] * H[0][1] * H[0][1];
+ H[1][2] = (H[2][1] - H[0][1] * H[2][0]) / H[1][1];
+ H[1][3] = (H[3][1] - H[0][1] * H[3][0]) / H[1][1];
+ H[2][2] -= H[0][0] * H[0][2] * H[0][2] + H[1][1] * H[1][2] * H[1][2];
+ H[2][3] = (H[3][2] - H[0][2] * H[3][0] - H[1][2] * H[1][1] * H[1][3]) / H[2][2];
+ H[3][3] -= H[0][0] * H[0][3] * H[0][3] + H[1][1] * H[1][3] * H[1][3] + H[2][2] * H[2][3] * H[2][3];
+
+ /* Compute update as delta_gains = -inv(H) * grad */
+ /* copy and negate */
+ for (k = 0; k < 4; k++)
+ dG[k] = -grad[k];
+ /* back substitution */
+ dG[1] -= dG[0] * H[0][1];
+ dG[2] -= dG[0] * H[0][2] + dG[1] * H[1][2];
+ dG[3] -= dG[0] * H[0][3] + dG[1] * H[1][3] + dG[2] * H[2][3];
+ /* scale */
+ for (k = 0; k < 4; k++)
+ dG[k] /= H[k][k];
+ /* back substitution */
+ dG[2] -= dG[3] * H[2][3];
+ dG[1] -= dG[3] * H[1][3] + dG[2] * H[1][2];
+ dG[0] -= dG[3] * H[0][3] + dG[2] * H[0][2] + dG[1] * H[0][1];
+
+ /* update gains and check range */
+ for (k = 0; k < 4; k++) {
+ gains[k] += dG[k];
+ if (gains[k] > PITCH_MAX_GAIN)
+ gains[k] = PITCH_MAX_GAIN;
+ else if (gains[k] < 0.0)
+ gains[k] = 0.0;
+ }
+ }
+
+ /* update state for next frame */
+ WebRtcIsac_PitchfilterPre(Whitened, out, &(State->PFstr_wght), lags, gains);
+
+ /* concatenate previous input's end and current input */
+ memcpy(inbuf, State->inbuf, sizeof(double) * QLOOKAHEAD);
+ memcpy(inbuf+QLOOKAHEAD, in, sizeof(double) * PITCH_FRAME_LEN);
+
+ /* lookahead pitch filtering for masking analysis */
+ WebRtcIsac_PitchfilterPre_la(inbuf, out, &(State->PFstr), lags, gains);
+
+ /* store last part of input */
+ for (k = 0; k < QLOOKAHEAD; k++)
+ State->inbuf[k] = inbuf[k + PITCH_FRAME_LEN];
+}
diff --git a/src/mod/codecs/mod_isac/pitch_estimator.h b/src/mod/codecs/mod_isac/pitch_estimator.h
new file mode 100644
index 0000000000..f5d93564be
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_estimator.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_estimator.h
+ *
+ * Pitch functions
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_
+
+#include "structs.h"
+
+
+
+void WebRtcIsac_PitchAnalysis(const double *in, /* PITCH_FRAME_LEN samples */
+ double *out, /* PITCH_FRAME_LEN+QLOOKAHEAD samples */
+ PitchAnalysisStruct *State,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_InitializePitch(const double *in,
+ const double old_lag,
+ const double old_gain,
+ PitchAnalysisStruct *State,
+ double *lags);
+
+void WebRtcIsac_PitchfilterPre(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPost(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPre_la(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_PitchfilterPre_gains(double *indat,
+ double *outdat,
+ double out_dG[][PITCH_FRAME_LEN + QLOOKAHEAD],
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains);
+
+void WebRtcIsac_WeightingFilter(const double *in, double *weiout, double *whiout, WeightFiltstr *wfdata);
+
+void WebRtcIsac_Highpass(const double *in, double *out, double *state, int N);
+
+void WebRtcIsac_DecimateAllpass(const double *in,
+ double *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */
+ int N, /* number of input samples */
+ double *out); /* array of size N/2 */
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_ESTIMATOR_H_ */
diff --git a/src/mod/codecs/mod_isac/pitch_filter.c b/src/mod/codecs/mod_isac/pitch_filter.c
new file mode 100644
index 0000000000..ccc8d214da
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_filter.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_estimator.h"
+#include "os_specific_inline.h"
+
+#include
+#include
+#include
+
+static const double kDampFilter[PITCH_DAMPORDER] = {-0.07, 0.25, 0.64, 0.25, -0.07};
+
+/* interpolation coefficients; generated by design_pitch_filter.m */
+static const double kIntrpCoef[PITCH_FRACS][PITCH_FRACORDER] = {
+ {-0.02239172458614, 0.06653315052934, -0.16515880017569, 0.60701333734125, 0.64671399919202, -0.20249000396417, 0.09926548334755, -0.04765933793109, 0.01754159521746},
+ {-0.01985640750434, 0.05816126837866, -0.13991265473714, 0.44560418147643, 0.79117042386876, -0.20266133815188, 0.09585268418555, -0.04533310458084, 0.01654127246314},
+ {-0.01463300534216, 0.04229888475060, -0.09897034715253, 0.28284326017787, 0.90385267956632, -0.16976950138649, 0.07704272393639, -0.03584218578311, 0.01295781500709},
+ {-0.00764851320885, 0.02184035544377, -0.04985561057281, 0.13083306574393, 0.97545011664662, -0.10177807997561, 0.04400901776474, -0.02010737175166, 0.00719783432422},
+ {-0.00000000000000, 0.00000000000000, -0.00000000000001, 0.00000000000001, 0.99999999999999, 0.00000000000001, -0.00000000000001, 0.00000000000000, -0.00000000000000},
+ { 0.00719783432422, -0.02010737175166, 0.04400901776474, -0.10177807997562, 0.97545011664663, 0.13083306574393, -0.04985561057280, 0.02184035544377, -0.00764851320885},
+ { 0.01295781500710, -0.03584218578312, 0.07704272393640, -0.16976950138650, 0.90385267956634, 0.28284326017785, -0.09897034715252, 0.04229888475059, -0.01463300534216},
+ { 0.01654127246315, -0.04533310458085, 0.09585268418557, -0.20266133815190, 0.79117042386878, 0.44560418147640, -0.13991265473712, 0.05816126837865, -0.01985640750433}
+};
+
+
+void WebRtcIsac_PitchfilterPre(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains)
+{
+
+ double ubuf[PITCH_INTBUFFSIZE];
+ const double *fracoeff = NULL;
+ double curgain, curlag, gaindelta, lagdelta;
+ double sum, inystate[PITCH_DAMPORDER];
+ double ftmp, oldlag, oldgain;
+ int k, n, m, pos, ind, pos2, Li, frc;
+
+ Li = 0;
+ /* Set up buffer and states */
+ memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER);
+
+ oldlag = *pfp->oldlagp;
+ oldgain = *pfp->oldgainp;
+
+ /* No interpolation if pitch lag step is big */
+ if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) {
+ oldlag = lags[0];
+ oldgain = gains[0];
+ }
+
+ ind=0;
+ for (k=0;k0;m--)
+ inystate[m] = inystate[m-1];
+
+ /* Filter to get fractional pitch */
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+ sum=0;
+ for (m=0;mubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER);
+
+ *pfp->oldlagp = oldlag;
+ *pfp->oldgainp = oldgain;
+
+}
+
+
+void WebRtcIsac_PitchfilterPre_la(double *indat,
+ double *outdat,
+ PitchFiltstr *pfp,
+ double *lags,
+ double *gains)
+{
+ double ubuf[PITCH_INTBUFFSIZE+QLOOKAHEAD];
+ const double *fracoeff = NULL;
+ double curgain, curlag, gaindelta, lagdelta;
+ double sum, inystate[PITCH_DAMPORDER];
+ double ftmp;
+ double oldlag, oldgain;
+ int k, n, m, pos, ind, pos2, Li, frc;
+
+ Li = 0;
+ /* Set up buffer and states */
+ memcpy(ubuf, pfp->ubuf, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER);
+
+ oldlag = *pfp->oldlagp;
+ oldgain = *pfp->oldgainp;
+
+ /* No interpolation if pitch lag step is big */
+ if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) {
+ oldlag = lags[0];
+ oldgain = gains[0];
+ }
+
+
+ ind=0;
+ for (k=0;k0;m--)
+ inystate[m] = inystate[m-1];
+
+ /* Filter to get fractional pitch */
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+ sum=0.0;
+ for (m=0;mubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER);
+
+ *pfp->oldlagp = oldlag;
+ *pfp->oldgainp = oldgain;
+
+
+ /* Filter look-ahead segment */
+ for (n=0;n0;m--)
+ inystate[m] = inystate[m-1];
+
+ /* Filter to get fractional pitch */
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+ sum=0.0;
+ for (m=0;mubuf, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER);
+
+ /* clear some buffers */
+ for (k = 0; k < 4; k++) {
+ gain_mult[k] = 0.0;
+ for (n = 0; n < PITCH_DAMPORDER; n++)
+ inystate_dG[k][n] = 0.0;
+ }
+
+ oldlag = *pfp->oldlagp;
+ oldgain = *pfp->oldgainp;
+
+ /* No interpolation if pitch lag step is big */
+ if ((lags[0] > (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) {
+ oldlag = lags[0];
+ oldgain = gains[0];
+ gain_mult[0] = 1.0;
+ }
+
+
+ ind=0;
+ for (k=0;k 1.0) gain_mult[k] = 1.0;
+ if (k > 0) gain_mult[k-1] -= 0.2;
+ }
+
+ /* shift low pass filter states */
+ for (m=PITCH_DAMPORDER-1;m>0;m--) {
+ inystate[m] = inystate[m-1];
+ for (j = 0; j < 4; j++)
+ inystate_dG[j][m] = inystate_dG[j][m-1];
+ }
+
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+
+ /* Filter to get fractional pitch */
+ sum=0.0;
+ for (m=0;m 0) ? Li-ind : 0;
+ for (j = 0; j < k+1; j++) {
+ /* filter */
+ sum2 = 0.0;
+ for (m = PITCH_FRACORDER-1; m >= m_tmp; m--)
+ sum2 += out_dG[j][ind-Li + m] * fracoeff[m];
+ inystate_dG[j][0] = gain_mult[j] * sum + curgain * sum2;
+ }
+
+ /* Low pass filter */
+ sum=0.0;
+ for (m=0;m0;m--) {
+ inystate[m] = inystate[m-1];
+ for (j = 0; j < 4; j++)
+ inystate_dG[j][m] = inystate_dG[j][m-1];
+ }
+
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+
+ /* Filter to get fractional pitch */
+ sum=0.0;
+ for (m=0;m 0) ? Li-ind : 0;
+ for (j = 0; (j= m_tmp; m--)
+ sum2 += out_dG[j][ind-Li + m] * fracoeff[m];
+ inystate_dG[j][0] = gain_mult[j] * sum + curgain * sum2;
+ }
+
+ /* Low pass filter */
+ sum=0.0;
+ for (m=0;mubuf, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(inystate, pfp->ystate, sizeof(double) * PITCH_DAMPORDER);
+
+ oldlag = *pfp->oldlagp;
+ oldgain = *pfp->oldgainp;
+
+ /* make output more periodic */
+ for (k=0;k (PITCH_UPSTEP * oldlag)) || (lags[0] < (PITCH_DOWNSTEP * oldlag))) {
+ oldlag = lags[0];
+ oldgain = gains[0];
+ }
+
+
+ ind=0;
+ for (k=0;k0;m--)
+ inystate[m] = inystate[m-1];
+
+ /* Filter to get fractional pitch */
+ pos = ind + PITCH_BUFFSIZE;
+ pos2 = pos - Li;
+ sum=0.0;
+ for (m=0;mubuf, ubuf+PITCH_FRAME_LEN, sizeof(double) * PITCH_BUFFSIZE);
+ memcpy(pfp->ystate, inystate, sizeof(double) * PITCH_DAMPORDER);
+
+ *pfp->oldlagp = oldlag;
+ *pfp->oldgainp = oldgain;
+
+}
diff --git a/src/mod/codecs/mod_isac/pitch_gain_tables.c b/src/mod/codecs/mod_isac/pitch_gain_tables.c
new file mode 100644
index 0000000000..5d998a2928
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_gain_tables.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_gain_tables.h"
+
+#include "settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+const WebRtc_UWord16 WebRtcIsac_kQPitchGainCdf[255] = {
+ 0, 2, 4, 6, 64, 901, 903, 905, 16954, 16956,
+ 16961, 17360, 17362, 17364, 17366, 17368, 17370, 17372, 17374, 17411,
+ 17514, 17516, 17583, 18790, 18796, 18802, 20760, 20777, 20782, 21722,
+ 21724, 21728, 21738, 21740, 21742, 21744, 21746, 21748, 22224, 22227,
+ 22230, 23214, 23229, 23239, 25086, 25108, 25120, 26088, 26094, 26098,
+ 26175, 26177, 26179, 26181, 26183, 26185, 26484, 26507, 26522, 27705,
+ 27731, 27750, 29767, 29799, 29817, 30866, 30883, 30885, 31025, 31029,
+ 31031, 31033, 31035, 31037, 31114, 31126, 31134, 32687, 32722, 32767,
+ 35718, 35742, 35757, 36943, 36952, 36954, 37115, 37128, 37130, 37132,
+ 37134, 37136, 37143, 37145, 37152, 38843, 38863, 38897, 47458, 47467,
+ 47474, 49040, 49061, 49063, 49145, 49157, 49159, 49161, 49163, 49165,
+ 49167, 49169, 49171, 49757, 49770, 49782, 61333, 61344, 61346, 62860,
+ 62883, 62885, 62887, 62889, 62891, 62893, 62895, 62897, 62899, 62901,
+ 62903, 62905, 62907, 62909, 65496, 65498, 65500, 65521, 65523, 65525,
+ 65527, 65529, 65531, 65533, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kIndexLowerLimitGain[3] = {
+ -7, -2, -1};
+
+const WebRtc_Word16 WebRtcIsac_kIndexUpperLimitGain[3] = {
+ 0, 3, 1};
+
+const WebRtc_UWord16 WebRtcIsac_kIndexMultsGain[2] = {
+ 18, 3};
+
+/* size of cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQCdfTableSizeGain[1] = {
+ 256};
+
+///////////////////////////FIXED POINT
+/* mean values of pitch filter gains in FIXED point */
+const WebRtc_Word16 WebRtcIsac_kQMeanGain1Q12[144] = {
+ 843, 1092, 1336, 1222, 1405, 1656, 1500, 1815, 1843, 1838, 1839, 1843, 1843, 1843, 1843, 1843,
+ 1843, 1843, 814, 846, 1092, 1013, 1174, 1383, 1391, 1511, 1584, 1734, 1753, 1843, 1843, 1843,
+ 1843, 1843, 1843, 1843, 524, 689, 777, 845, 947, 1069, 1090, 1263, 1380, 1447, 1559, 1676,
+ 1645, 1749, 1843, 1843, 1843, 1843, 81, 477, 563, 611, 706, 806, 849, 1012, 1192, 1128,
+ 1330, 1489, 1425, 1576, 1826, 1741, 1843, 1843, 0, 290, 305, 356, 488, 575, 602, 741,
+ 890, 835, 1079, 1196, 1182, 1376, 1519, 1506, 1680, 1843, 0, 47, 97, 69, 289, 381,
+ 385, 474, 617, 664, 803, 1079, 935, 1160, 1269, 1265, 1506, 1741, 0, 0, 0, 0,
+ 112, 120, 190, 283, 442, 343, 526, 809, 684, 935, 1134, 1020, 1265, 1506, 0, 0,
+ 0, 0, 0, 0, 0, 111, 256, 87, 373, 597, 430, 684, 935, 770, 1020, 1265};
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain2Q12[144] = {
+ 1760, 1525, 1285, 1747, 1671, 1393, 1843, 1826, 1555, 1843, 1784, 1606, 1843, 1843, 1711, 1843,
+ 1843, 1814, 1389, 1275, 1040, 1564, 1414, 1252, 1610, 1495, 1343, 1753, 1592, 1405, 1804, 1720,
+ 1475, 1843, 1814, 1581, 1208, 1061, 856, 1349, 1148, 994, 1390, 1253, 1111, 1495, 1343, 1178,
+ 1770, 1465, 1234, 1814, 1581, 1342, 1040, 793, 713, 1053, 895, 737, 1128, 1003, 861, 1277,
+ 1094, 981, 1475, 1192, 1019, 1581, 1342, 1098, 855, 570, 483, 833, 648, 540, 948, 744,
+ 572, 1009, 844, 636, 1234, 934, 685, 1342, 1217, 984, 537, 318, 124, 603, 423, 350,
+ 687, 479, 322, 791, 581, 430, 987, 671, 488, 1098, 849, 597, 283, 27, 0, 397,
+ 222, 38, 513, 271, 124, 624, 325, 157, 737, 484, 233, 849, 597, 343, 27, 0,
+ 0, 141, 0, 0, 256, 69, 0, 370, 87, 0, 484, 229, 0, 597, 343, 87};
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain3Q12[144] = {
+ 1843, 1843, 1711, 1843, 1818, 1606, 1843, 1827, 1511, 1814, 1639, 1393, 1760, 1525, 1285, 1656,
+ 1419, 1176, 1835, 1718, 1475, 1841, 1650, 1387, 1648, 1498, 1287, 1600, 1411, 1176, 1522, 1299,
+ 1040, 1419, 1176, 928, 1773, 1461, 1128, 1532, 1355, 1202, 1429, 1260, 1115, 1398, 1151, 1025,
+ 1172, 1080, 790, 1176, 928, 677, 1475, 1147, 1019, 1276, 1096, 922, 1214, 1010, 901, 1057,
+ 893, 800, 1040, 796, 734, 928, 677, 424, 1137, 897, 753, 1120, 830, 710, 875, 751,
+ 601, 795, 642, 583, 790, 544, 475, 677, 474, 140, 987, 750, 482, 697, 573, 450,
+ 691, 487, 303, 661, 394, 332, 537, 303, 220, 424, 168, 0, 737, 484, 229, 624,
+ 348, 153, 441, 261, 136, 397, 166, 51, 283, 27, 0, 168, 0, 0, 484, 229,
+ 0, 370, 57, 0, 256, 43, 0, 141, 0, 0, 27, 0, 0, 0, 0, 0};
+
+
+const WebRtc_Word16 WebRtcIsac_kQMeanGain4Q12[144] = {
+ 1843, 1843, 1843, 1843, 1841, 1843, 1500, 1821, 1843, 1222, 1434, 1656, 843, 1092, 1336, 504,
+ 757, 1007, 1843, 1843, 1843, 1838, 1791, 1843, 1265, 1505, 1599, 965, 1219, 1425, 730, 821,
+ 1092, 249, 504, 757, 1783, 1819, 1843, 1351, 1567, 1727, 1096, 1268, 1409, 805, 961, 1131,
+ 444, 670, 843, 0, 249, 504, 1425, 1655, 1743, 1096, 1324, 1448, 822, 1019, 1199, 490,
+ 704, 867, 81, 450, 555, 0, 0, 249, 1247, 1428, 1530, 881, 1073, 1283, 610, 759,
+ 939, 278, 464, 645, 0, 200, 270, 0, 0, 0, 935, 1163, 1410, 528, 790, 1068,
+ 377, 499, 717, 173, 240, 274, 0, 43, 62, 0, 0, 0, 684, 935, 1182, 343,
+ 551, 735, 161, 262, 423, 0, 55, 27, 0, 0, 0, 0, 0, 0, 430, 684,
+ 935, 87, 377, 597, 0, 46, 256, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/src/mod/codecs/mod_isac/pitch_gain_tables.h b/src/mod/codecs/mod_isac/pitch_gain_tables.h
new file mode 100644
index 0000000000..f958f5df45
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_gain_tables.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_gain_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
+
+#include "typedefs.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+/* cdf for quantized pitch filter gains */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchGainCdf[255];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kIndexLowerLimitGain[3];
+
+extern const WebRtc_Word16 WebRtcIsac_kIndexUpperLimitGain[3];
+extern const WebRtc_UWord16 WebRtcIsac_kIndexMultsGain[2];
+
+/* mean values of pitch filter gains */
+//(Y)
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain1Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain2Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain3Q12[144];
+extern const WebRtc_Word16 WebRtcIsac_kQMeanGain4Q12[144];
+//(Y)
+
+/* size of cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQCdfTableSizeGain[1];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_ */
diff --git a/src/mod/codecs/mod_isac/pitch_lag_tables.c b/src/mod/codecs/mod_isac/pitch_lag_tables.c
new file mode 100644
index 0000000000..72a031e227
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_lag_tables.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pitch_lag_tables.h"
+#include "settings.h"
+
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Gain Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Lo[127] = {
+ 0, 134, 336, 549, 778, 998, 1264, 1512, 1777, 2070,
+ 2423, 2794, 3051, 3361, 3708, 3979, 4315, 4610, 4933, 5269,
+ 5575, 5896, 6155, 6480, 6816, 7129, 7477, 7764, 8061, 8358,
+ 8718, 9020, 9390, 9783, 10177, 10543, 10885, 11342, 11795, 12213,
+ 12680, 13096, 13524, 13919, 14436, 14903, 15349, 15795, 16267, 16734,
+ 17266, 17697, 18130, 18632, 19080, 19447, 19884, 20315, 20735, 21288,
+ 21764, 22264, 22723, 23193, 23680, 24111, 24557, 25022, 25537, 26082,
+ 26543, 27090, 27620, 28139, 28652, 29149, 29634, 30175, 30692, 31273,
+ 31866, 32506, 33059, 33650, 34296, 34955, 35629, 36295, 36967, 37726,
+ 38559, 39458, 40364, 41293, 42256, 43215, 44231, 45253, 46274, 47359,
+ 48482, 49678, 50810, 51853, 53016, 54148, 55235, 56263, 57282, 58363,
+ 59288, 60179, 61076, 61806, 62474, 63129, 63656, 64160, 64533, 64856,
+ 65152, 65535, 65535, 65535, 65535, 65535, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Lo[20] = {
+ 0, 429, 3558, 5861, 8558, 11639, 15210, 19502, 24773, 31983,
+ 42602, 48567, 52601, 55676, 58160, 60172, 61889, 63235, 65383, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Lo[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Lo[10] = {
+ 0, 2966, 6368, 11182, 19431, 37793, 48532, 55353, 60626, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrLo[4] = {WebRtcIsac_kQPitchLagCdf1Lo, WebRtcIsac_kQPitchLagCdf2Lo, WebRtcIsac_kQPitchLagCdf3Lo, WebRtcIsac_kQPitchLagCdf4Lo};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeLo[1] = {128};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagLo[4] = {
+-140, -9, 0, -4};
+
+const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagLo[4] = {
+-20, 9, 0, 4};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagLo[3] = {
+ 10, 1, 5};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Lo[19] = {
+-17.21385070, -15.82678944, -14.07123081, -12.03003877, -10.01311864, -8.00794627, -5.91162987, -3.89231876, -1.90220980, -0.01879275,
+ 1.89144232, 3.88123171, 5.92146992, 7.96435361, 9.98923648, 11.98266347, 13.96101002, 15.74855713, 17.10976611};
+
+const double WebRtcIsac_kQMeanLag3Lo[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Lo[9] = {
+-7.76246496, -5.92083980, -3.94095226, -1.89502305, 0.03724681, 1.93054221, 3.96443467, 5.91726366, 7.78434291};
+
+const double WebRtcIsac_kQPitchLagStepsizeLo = 2.000000;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Mid[255] = {
+ 0, 28, 61, 88, 121, 149, 233, 331, 475, 559,
+ 624, 661, 689, 712, 745, 791, 815, 843, 866, 922,
+ 959, 1024, 1061, 1117, 1178, 1238, 1280, 1350, 1453, 1513,
+ 1564, 1625, 1671, 1741, 1788, 1904, 2072, 2421, 2626, 2770,
+ 2840, 2900, 2942, 3012, 3068, 3115, 3147, 3194, 3254, 3319,
+ 3366, 3520, 3678, 3780, 3850, 3911, 3957, 4032, 4106, 4185,
+ 4292, 4474, 4683, 4842, 5019, 5191, 5321, 5428, 5540, 5675,
+ 5763, 5847, 5959, 6127, 6304, 6564, 6839, 7090, 7263, 7421,
+ 7556, 7728, 7872, 7984, 8142, 8361, 8580, 8743, 8938, 9227,
+ 9409, 9539, 9674, 9795, 9930, 10060, 10177, 10382, 10614, 10861,
+ 11038, 11271, 11415, 11629, 11792, 12044, 12193, 12416, 12574, 12821,
+ 13007, 13235, 13445, 13654, 13901, 14134, 14488, 15000, 15703, 16285,
+ 16504, 16797, 17086, 17328, 17579, 17807, 17998, 18268, 18538, 18836,
+ 19087, 19274, 19474, 19716, 19935, 20270, 20833, 21303, 21532, 21741,
+ 21978, 22207, 22523, 22770, 23054, 23613, 23943, 24204, 24399, 24651,
+ 24832, 25074, 25270, 25549, 25759, 26015, 26150, 26424, 26713, 27048,
+ 27342, 27504, 27681, 27854, 28021, 28207, 28412, 28664, 28859, 29064,
+ 29278, 29548, 29748, 30107, 30377, 30656, 30856, 31164, 31452, 31755,
+ 32011, 32328, 32626, 32919, 33319, 33789, 34329, 34925, 35396, 35973,
+ 36443, 36964, 37551, 38156, 38724, 39357, 40023, 40908, 41587, 42602,
+ 43924, 45037, 45810, 46597, 47421, 48291, 49092, 50051, 51448, 52719,
+ 53440, 54241, 54944, 55977, 56676, 57299, 57872, 58389, 59059, 59688,
+ 60237, 60782, 61094, 61573, 61890, 62290, 62658, 63030, 63217, 63454,
+ 63622, 63882, 64003, 64273, 64427, 64529, 64581, 64697, 64758, 64902,
+ 65414, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Mid[36] = {
+ 0, 71, 335, 581, 836, 1039, 1323, 1795, 2258, 2608,
+ 3005, 3591, 4243, 5344, 7163, 10583, 16848, 28078, 49448, 57007,
+ 60357, 61850, 62837, 63437, 63872, 64188, 64377, 64614, 64774, 64949,
+ 65039, 65115, 65223, 65360, 65474, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Mid[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Mid[20] = {
+ 0, 28, 246, 459, 667, 1045, 1523, 2337, 4337, 11347,
+ 44231, 56709, 60781, 62243, 63161, 63969, 64608, 65062, 65502, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrMid[4] = {WebRtcIsac_kQPitchLagCdf1Mid, WebRtcIsac_kQPitchLagCdf2Mid, WebRtcIsac_kQPitchLagCdf3Mid, WebRtcIsac_kQPitchLagCdf4Mid};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeMid[1] = {256};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagMid[4] = {
+-280, -17, 0, -9};
+
+const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagMid[4] = {
+-40, 17, 0, 9};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagMid[3] = {
+ 18, 1, 10};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Mid[35] = {
+-16.89183900, -15.86949778, -15.05476653, -14.00664348, -13.02793036, -12.07324237, -11.00542532, -10.11250602, -8.90792971, -8.02474753,
+-7.00426767, -5.94055287, -4.98251338, -3.91053158, -2.98820425, -1.93524245, -0.92978085, -0.01722509, 0.91317387, 1.92973955,
+ 2.96908851, 3.93728974, 4.96308471, 5.92244151, 7.08673497, 8.00993708, 9.04656316, 9.98538742, 10.97851694, 11.94772884,
+ 13.02426166, 14.00039951, 15.01347042, 15.80758023, 16.94086895};
+
+const double WebRtcIsac_kQMeanLag3Mid[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Mid[19] = {
+-8.60409403, -7.89198395, -7.03450280, -5.86260421, -4.93822322, -3.93078706, -2.91302322, -1.91824007, -0.87003282, 0.02822649,
+ 0.89951758, 1.87495484, 2.91802604, 3.96874074, 5.06571703, 5.93618227, 7.00520185, 7.88497726, 8.64160364};
+
+const double WebRtcIsac_kQPitchLagStepsizeMid = 1.000000;
+
+
+/* tables for use with large pitch gain */
+
+/* cdf for quantized pitch filter lags */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Hi[511] = {
+ 0, 7, 18, 33, 69, 105, 156, 228, 315, 612,
+ 680, 691, 709, 724, 735, 738, 742, 746, 749, 753,
+ 756, 760, 764, 774, 782, 785, 789, 796, 800, 803,
+ 807, 814, 818, 822, 829, 832, 847, 854, 858, 869,
+ 876, 883, 898, 908, 934, 977, 1010, 1050, 1060, 1064,
+ 1075, 1078, 1086, 1089, 1093, 1104, 1111, 1122, 1133, 1136,
+ 1151, 1162, 1183, 1209, 1252, 1281, 1339, 1364, 1386, 1401,
+ 1411, 1415, 1426, 1430, 1433, 1440, 1448, 1455, 1462, 1477,
+ 1487, 1495, 1502, 1506, 1509, 1516, 1524, 1531, 1535, 1542,
+ 1553, 1556, 1578, 1589, 1611, 1625, 1639, 1643, 1654, 1665,
+ 1672, 1687, 1694, 1705, 1708, 1719, 1730, 1744, 1752, 1759,
+ 1791, 1795, 1820, 1867, 1886, 1915, 1936, 1943, 1965, 1987,
+ 2041, 2099, 2161, 2175, 2200, 2211, 2226, 2233, 2244, 2251,
+ 2266, 2280, 2287, 2298, 2309, 2316, 2331, 2342, 2356, 2378,
+ 2403, 2418, 2447, 2497, 2544, 2602, 2863, 2895, 2903, 2935,
+ 2950, 2971, 3004, 3011, 3018, 3029, 3040, 3062, 3087, 3127,
+ 3152, 3170, 3199, 3243, 3293, 3322, 3340, 3377, 3402, 3427,
+ 3474, 3518, 3543, 3579, 3601, 3637, 3659, 3706, 3731, 3760,
+ 3818, 3847, 3869, 3901, 3920, 3952, 4068, 4169, 4220, 4271,
+ 4524, 4571, 4604, 4632, 4672, 4730, 4777, 4806, 4857, 4904,
+ 4951, 5002, 5031, 5060, 5107, 5150, 5212, 5266, 5331, 5382,
+ 5432, 5490, 5544, 5610, 5700, 5762, 5812, 5874, 5972, 6022,
+ 6091, 6163, 6232, 6305, 6402, 6540, 6685, 6880, 7090, 7271,
+ 7379, 7452, 7542, 7625, 7687, 7770, 7843, 7911, 7966, 8024,
+ 8096, 8190, 8252, 8320, 8411, 8501, 8585, 8639, 8751, 8842,
+ 8918, 8986, 9066, 9127, 9203, 9269, 9345, 9406, 9464, 9536,
+ 9612, 9667, 9735, 9844, 9931, 10036, 10119, 10199, 10260, 10358,
+ 10441, 10514, 10666, 10734, 10872, 10951, 11053, 11125, 11223, 11324,
+ 11516, 11664, 11737, 11816, 11892, 12008, 12120, 12200, 12280, 12392,
+ 12490, 12576, 12685, 12812, 12917, 13003, 13108, 13210, 13300, 13384,
+ 13470, 13579, 13673, 13771, 13879, 13999, 14136, 14201, 14368, 14614,
+ 14759, 14867, 14958, 15030, 15121, 15189, 15280, 15385, 15461, 15555,
+ 15653, 15768, 15884, 15971, 16069, 16145, 16210, 16279, 16380, 16463,
+ 16539, 16615, 16688, 16818, 16919, 17017, 18041, 18338, 18523, 18649,
+ 18790, 18917, 19047, 19167, 19315, 19460, 19601, 19731, 19858, 20068,
+ 20173, 20318, 20466, 20625, 20741, 20911, 21045, 21201, 21396, 21588,
+ 21816, 22022, 22305, 22547, 22786, 23072, 23322, 23600, 23879, 24168,
+ 24433, 24769, 25120, 25511, 25895, 26289, 26792, 27219, 27683, 28077,
+ 28566, 29094, 29546, 29977, 30491, 30991, 31573, 32105, 32594, 33173,
+ 33788, 34497, 35181, 35833, 36488, 37255, 37921, 38645, 39275, 39894,
+ 40505, 41167, 41790, 42431, 43096, 43723, 44385, 45134, 45858, 46607,
+ 47349, 48091, 48768, 49405, 49955, 50555, 51167, 51985, 52611, 53078,
+ 53494, 53965, 54435, 54996, 55601, 56125, 56563, 56838, 57244, 57566,
+ 57967, 58297, 58771, 59093, 59419, 59647, 59886, 60143, 60461, 60693,
+ 60917, 61170, 61416, 61634, 61891, 62122, 62310, 62455, 62632, 62839,
+ 63103, 63436, 63639, 63805, 63906, 64015, 64192, 64355, 64475, 64558,
+ 64663, 64742, 64811, 64865, 64916, 64956, 64981, 65025, 65068, 65115,
+ 65195, 65314, 65419, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+ 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Hi[68] = {
+ 0, 7, 11, 22, 37, 52, 56, 59, 81, 85,
+ 89, 96, 115, 130, 137, 152, 170, 181, 193, 200,
+ 207, 233, 237, 259, 289, 318, 363, 433, 592, 992,
+ 1607, 3062, 6149, 12206, 25522, 48368, 58223, 61918, 63640, 64584,
+ 64943, 65098, 65206, 65268, 65294, 65335, 65350, 65372, 65387, 65402,
+ 65413, 65420, 65428, 65435, 65439, 65450, 65454, 65468, 65472, 65476,
+ 65483, 65491, 65498, 65505, 65516, 65520, 65528, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Hi[2] = {
+ 0, 65535};
+
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Hi[35] = {
+ 0, 7, 19, 30, 41, 48, 63, 74, 82, 96,
+ 122, 152, 215, 330, 701, 2611, 10931, 48106, 61177, 64341,
+ 65112, 65238, 65309, 65338, 65364, 65379, 65401, 65427, 65453, 65465,
+ 65476, 65490, 65509, 65528, 65535};
+
+const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrHi[4] = {WebRtcIsac_kQPitchLagCdf1Hi, WebRtcIsac_kQPitchLagCdf2Hi, WebRtcIsac_kQPitchLagCdf3Hi, WebRtcIsac_kQPitchLagCdf4Hi};
+
+/* size of first cdf table */
+const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeHi[1] = {512};
+
+/* index limits and ranges */
+const WebRtc_Word16 WebRtcIsac_kQindexLowerLimitLagHi[4] = {
+-552, -34, 0, -16};
+
+const WebRtc_Word16 WebRtcIsac_kQindexUpperLimitLagHi[4] = {
+-80, 32, 0, 17};
+
+/* initial index for arithmetic decoder */
+const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagHi[3] = {
+ 34, 1, 18};
+
+/* mean values of pitch filter lags */
+const double WebRtcIsac_kQMeanLag2Hi[67] = {
+-17.07263295, -16.50000000, -15.83966081, -15.55613708, -14.96948007, -14.50000000, -14.00000000, -13.48377986, -13.00000000, -12.50000000,
+-11.93199636, -11.44530414, -11.04197641, -10.39910301, -10.15202337, -9.51322461, -8.93357741, -8.46456632, -8.10270672, -7.53751847,
+-6.98686404, -6.50000000, -6.08463150, -5.46872991, -5.00864717, -4.50163760, -4.01382410, -3.43856708, -2.96898001, -2.46554810,
+-1.96861004, -1.47106701, -0.97197237, -0.46561654, -0.00531409, 0.45767857, 0.96777907, 1.47507903, 1.97740425, 2.46695420,
+ 3.00695774, 3.47167185, 4.02712538, 4.49280007, 5.01087640, 5.48191963, 6.04916550, 6.51511058, 6.97297819, 7.46565499,
+ 8.01489405, 8.39912001, 8.91819757, 9.50000000, 10.11654065, 10.50000000, 11.03712583, 11.50000000, 12.00000000, 12.38964346,
+ 12.89466127, 13.43657881, 13.96013840, 14.46279912, 15.00000000, 15.39412269, 15.96662441};
+
+const double WebRtcIsac_kQMeanLag3Hi[1] = {
+ 0.00000000};
+
+const double WebRtcIsac_kQMeanLag4Hi[34] = {
+-7.98331221, -7.47988769, -7.03626557, -6.52708003, -6.06982173, -5.51856292, -5.05827033, -4.45909878, -3.99125864, -3.45308135,
+-3.02328139, -2.47297273, -1.94341995, -1.44699056, -0.93612243, -0.43012406, 0.01120357, 0.44054812, 0.93199883, 1.45669587,
+ 1.97218322, 2.50187419, 2.98748690, 3.49343202, 4.01660147, 4.50984306, 5.01402683, 5.58936797, 5.91787793, 6.59998900,
+ 6.85034315, 7.53503316, 7.87711194, 8.53631648};
+
+const double WebRtcIsac_kQPitchLagStepsizeHi = 0.500000;
+
+/* transform matrix */
+const double WebRtcIsac_kTransform[4][4] = {
+{-0.50000000, -0.50000000, -0.50000000, -0.50000000},
+{ 0.67082039, 0.22360680, -0.22360680, -0.67082039},
+{ 0.50000000, -0.50000000, -0.50000000, 0.50000000},
+{ 0.22360680, -0.67082039, 0.67082039, -0.22360680}};
+
+/* transpose transform matrix */
+const double WebRtcIsac_kTransformTranspose[4][4] = {
+{-0.50000000, 0.67082039, 0.50000000, 0.22360680},
+{-0.50000000, 0.22360680, -0.50000000, -0.67082039},
+{-0.50000000, -0.22360680, -0.50000000, 0.67082039},
+{-0.50000000, -0.67082039, 0.50000000, -0.22360680}};
+
diff --git a/src/mod/codecs/mod_isac/pitch_lag_tables.h b/src/mod/codecs/mod_isac/pitch_lag_tables.h
new file mode 100644
index 0000000000..67b02e5e4d
--- /dev/null
+++ b/src/mod/codecs/mod_isac/pitch_lag_tables.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * pitch_lag_tables.h
+ *
+ * This file contains tables for the pitch filter side-info in the entropy coder.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
+
+#include "typedefs.h"
+/* header file for coding tables for the pitch filter side-info in the entropy coder */
+/********************* Pitch Filter Lag Coefficient Tables ************************/
+
+/* tables for use with small pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Lo[127];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Lo[20];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Lo[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Lo[10];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrLo[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeLo[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagLo[4];
+extern const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagLo[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagLo[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Lo[19];
+extern const double WebRtcIsac_kQMeanLag3Lo[1];
+extern const double WebRtcIsac_kQMeanLag4Lo[9];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeLo;
+
+
+/* tables for use with medium pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Mid[255];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Mid[36];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Mid[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Mid[20];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrMid[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeMid[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQIndexLowerLimitLagMid[4];
+extern const WebRtc_Word16 WebRtcIsac_kQIndexUpperLimitLagMid[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagMid[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Mid[35];
+extern const double WebRtcIsac_kQMeanLag3Mid[1];
+extern const double WebRtcIsac_kQMeanLag4Mid[19];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeMid;
+
+
+/* tables for use with large pitch gain */
+
+/* cdfs for quantized pitch lags */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf1Hi[511];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf2Hi[68];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf3Hi[2];
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdf4Hi[35];
+
+extern const WebRtc_UWord16 *WebRtcIsac_kQPitchLagCdfPtrHi[4];
+
+/* size of first cdf table */
+extern const WebRtc_UWord16 WebRtcIsac_kQPitchLagCdfSizeHi[1];
+
+/* index limits and ranges */
+extern const WebRtc_Word16 WebRtcIsac_kQindexLowerLimitLagHi[4];
+extern const WebRtc_Word16 WebRtcIsac_kQindexUpperLimitLagHi[4];
+
+/* initial index for arithmetic decoder */
+extern const WebRtc_UWord16 WebRtcIsac_kQInitIndexLagHi[3];
+
+/* mean values of pitch filter lags */
+extern const double WebRtcIsac_kQMeanLag2Hi[67];
+extern const double WebRtcIsac_kQMeanLag3Hi[1];
+extern const double WebRtcIsac_kQMeanLag4Hi[34];
+
+extern const double WebRtcIsac_kQPitchLagStepsizeHi;
+
+/* transform matrix */
+extern const double WebRtcIsac_kTransform[4][4];
+
+/* transpose transform matrix */
+extern const double WebRtcIsac_kTransformTranspose[4][4];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_ */
diff --git a/src/mod/codecs/mod_isac/randomization_functions.c b/src/mod/codecs/mod_isac/randomization_functions.c
new file mode 100644
index 0000000000..04271ada4d
--- /dev/null
+++ b/src/mod/codecs/mod_isac/randomization_functions.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains implementations of the randomization functions
+ * WebRtcSpl_IncreaseSeed()
+ * WebRtcSpl_RandU()
+ * WebRtcSpl_RandN()
+ * WebRtcSpl_RandUArray()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+static const WebRtc_Word16 kRandNTable[] = {
+ 9178, -7260, 40, 10189, 4894, -3531, -13779, 14764,
+ -4008, -8884, -8990, 1008, 7368, 5184, 3251, -5817,
+ -9786, 5963, 1770, 8066, -7135, 10772, -2298, 1361,
+ 6484, 2241, -8633, 792, 199, -3344, 6553, -10079,
+ -15040, 95, 11608, -12469, 14161, -4176, 2476, 6403,
+ 13685, -16005, 6646, 2239, 10916, -3004, -602, -3141,
+ 2142, 14144, -5829, 5305, 8209, 4713, 2697, -5112,
+ 16092, -1210, -2891, -6631, -5360, -11878, -6781, -2739,
+ -6392, 536, 10923, 10872, 5059, -4748, -7770, 5477,
+ 38, -1025, -2892, 1638, 6304, 14375, -11028, 1553,
+ -1565, 10762, -393, 4040, 5257, 12310, 6554, -4799,
+ 4899, -6354, 1603, -1048, -2220, 8247, -186, -8944,
+ -12004, 2332, 4801, -4933, 6371, 131, 8614, -5927,
+ -8287, -22760, 4033, -15162, 3385, 3246, 3153, -5250,
+ 3766, 784, 6494, -62, 3531, -1582, 15572, 662,
+ -3952, -330, -3196, 669, 7236, -2678, -6569, 23319,
+ -8645, -741, 14830, -15976, 4903, 315, -11342, 10311,
+ 1858, -7777, 2145, 5436, 5677, -113, -10033, 826,
+ -1353, 17210, 7768, 986, -1471, 8291, -4982, 8207,
+ -14911, -6255, -2449, -11881, -7059, -11703, -4338, 8025,
+ 7538, -2823, -12490, 9470, -1613, -2529, -10092, -7807,
+ 9480, 6970, -12844, 5123, 3532, 4816, 4803, -8455,
+ -5045, 14032, -4378, -1643, 5756, -11041, -2732, -16618,
+ -6430, -18375, -3320, 6098, 5131, -4269, -8840, 2482,
+ -7048, 1547, -21890, -6505, -7414, -424, -11722, 7955,
+ 1653, -17299, 1823, 473, -9232, 3337, 1111, 873,
+ 4018, -8982, 9889, 3531, -11763, -3799, 7373, -4539,
+ 3231, 7054, -8537, 7616, 6244, 16635, 447, -2915,
+ 13967, 705, -2669, -1520, -1771, -16188, 5956, 5117,
+ 6371, -9936, -1448, 2480, 5128, 7550, -8130, 5236,
+ 8213, -6443, 7707, -1950, -13811, 7218, 7031, -3883,
+ 67, 5731, -2874, 13480, -3743, 9298, -3280, 3552,
+ -4425, -18, -3785, -9988, -5357, 5477, -11794, 2117,
+ 1416, -9935, 3376, 802, -5079, -8243, 12652, 66,
+ 3653, -2368, 6781, -21895, -7227, 2487, 7839, -385,
+ 6646, -7016, -4658, 5531, -1705, 834, 129, 3694,
+ -1343, 2238, -22640, -6417, -11139, 11301, -2945, -3494,
+ -5626, 185, -3615, -2041, -7972, -3106, -60, -23497,
+ -1566, 17064, 3519, 2518, 304, -6805, -10269, 2105,
+ 1936, -426, -736, -8122, -1467, 4238, -6939, -13309,
+ 360, 7402, -7970, 12576, 3287, 12194, -6289, -16006,
+ 9171, 4042, -9193, 9123, -2512, 6388, -4734, -8739,
+ 1028, -5406, -1696, 5889, -666, -4736, 4971, 3565,
+ 9362, -6292, 3876, -3652, -19666, 7523, -4061, 391,
+ -11773, 7502, -3763, 4929, -9478, 13278, 2805, 4496,
+ 7814, 16419, 12455, -14773, 2127, -2746, 3763, 4847,
+ 3698, 6978, 4751, -6957, -3581, -45, 6252, 1513,
+ -4797, -7925, 11270, 16188, -2359, -5269, 9376, -10777,
+ 7262, 20031, -6515, -2208, -5353, 8085, -1341, -1303,
+ 7333, 5576, 3625, 5763, -7931, 9833, -3371, -10305,
+ 6534, -13539, -9971, 997, 8464, -4064, -1495, 1857,
+ 13624, 5458, 9490, -11086, -4524, 12022, -550, -198,
+ 408, -8455, -7068, 10289, 9712, -3366, 9028, -7621,
+ -5243, 2362, 6909, 4672, -4933, -1799, 4709, -4563,
+ -62, -566, 1624, -7010, 14730, -17791, -3697, -2344,
+ -1741, 7099, -9509, -6855, -1989, 3495, -2289, 2031,
+ 12784, 891, 14189, -3963, -5683, 421, -12575, 1724,
+ -12682, -5970, -8169, 3143, -1824, -5488, -5130, 8536,
+ 12799, 794, 5738, 3459, -11689, -258, -3738, -3775,
+ -8742, 2333, 8312, -9383, 10331, 13119, 8398, 10644,
+ -19433, -6446, -16277, -11793, 16284, 9345, 15222, 15834,
+ 2009, -7349, 130, -14547, 338, -5998, 3337, 21492,
+ 2406, 7703, -951, 11196, -564, 3406, 2217, 4806,
+ 2374, -5797, 11839, 8940, -11874, 18213, 2855, 10492
+};
+
+WebRtc_UWord32 WebRtcSpl_IncreaseSeed(WebRtc_UWord32 *seed)
+{
+ seed[0] = (seed[0] * ((WebRtc_Word32)69069) + 1) & (WEBRTC_SPL_MAX_SEED_USED - 1);
+ return seed[0];
+}
+
+WebRtc_Word16 WebRtcSpl_RandU(WebRtc_UWord32 *seed)
+{
+ return (WebRtc_Word16)(WebRtcSpl_IncreaseSeed(seed) >> 16);
+}
+
+WebRtc_Word16 WebRtcSpl_RandN(WebRtc_UWord32 *seed)
+{
+ return kRandNTable[WebRtcSpl_IncreaseSeed(seed) >> 23];
+}
+
+// Creates an array of uniformly distributed variables
+WebRtc_Word16 WebRtcSpl_RandUArray(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length,
+ WebRtc_UWord32* seed)
+{
+ int i;
+ for (i = 0; i < vector_length; i++)
+ {
+ vector[i] = WebRtcSpl_RandU(seed);
+ }
+ return vector_length;
+}
diff --git a/src/mod/codecs/mod_isac/refl_coef_to_lpc.c b/src/mod/codecs/mod_isac/refl_coef_to_lpc.c
new file mode 100644
index 0000000000..d07804dee7
--- /dev/null
+++ b/src/mod/codecs/mod_isac/refl_coef_to_lpc.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_ReflCoefToLpc().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16 *k, int use_order, WebRtc_Word16 *a)
+{
+ WebRtc_Word16 any[WEBRTC_SPL_MAX_LPC_ORDER + 1];
+ WebRtc_Word16 *aptr, *aptr2, *anyptr;
+ G_CONST WebRtc_Word16 *kptr;
+ int m, i;
+
+ kptr = k;
+ *a = 4096; // i.e., (Word16_MAX >> 3)+1.
+ *any = *a;
+ a[1] = WEBRTC_SPL_RSHIFT_W16((*k), 3);
+
+ for (m = 1; m < use_order; m++)
+ {
+ kptr++;
+ aptr = a;
+ aptr++;
+ aptr2 = &a[m];
+ anyptr = any;
+ anyptr++;
+
+ any[m + 1] = WEBRTC_SPL_RSHIFT_W16((*kptr), 3);
+ for (i = 0; i < m; i++)
+ {
+ *anyptr = (*aptr)
+ + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT((*aptr2), (*kptr), 15);
+ anyptr++;
+ aptr++;
+ aptr2--;
+ }
+
+ aptr = a;
+ anyptr = any;
+ for (i = 0; i < (m + 2); i++)
+ {
+ *aptr = *anyptr;
+ aptr++;
+ anyptr++;
+ }
+ }
+}
diff --git a/src/mod/codecs/mod_isac/resample.c b/src/mod/codecs/mod_isac/resample.c
new file mode 100644
index 0000000000..19d1778558
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the resampling functions for 22 kHz.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+#include "resample_by_2_internal.h"
+
+// Declaration of internally used functions
+static void WebRtcSpl_32khzTo22khzIntToShort(const WebRtc_Word32 *In, WebRtc_Word16 *Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_32khzTo22khzIntToInt(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K);
+
+// interpolation coefficients
+static const WebRtc_Word16 kCoefficients32To22[5][9] = {
+ {127, -712, 2359, -6333, 23456, 16775, -3695, 945, -154},
+ {-39, 230, -830, 2785, 32366, -2324, 760, -218, 38},
+ {117, -663, 2222, -6133, 26634, 13070, -3174, 831, -137},
+ {-77, 457, -1677, 5958, 31175, -4136, 1405, -408, 71},
+ { 98, -560, 1900, -5406, 29240, 9423, -2480, 663, -110}
+};
+
+//////////////////////
+// 22 kHz -> 16 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 4, 5, 10
+#define SUB_BLOCKS_22_16 5
+
+// 22 -> 16 resampler
+void WebRtcSpl_Resample22khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo16khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_22_16 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_22_16; k++)
+ {
+ ///// 22 --> 44 /////
+ // WebRtc_Word16 in[220/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[440/SUB_BLOCKS_22_16]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 220 / SUB_BLOCKS_22_16, tmpmem + 16, state->S_22_44);
+
+ ///// 44 --> 32 /////
+ // WebRtc_Word32 in[440/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[320/SUB_BLOCKS_22_16]
+ /////
+ // copy state to and from input array
+ tmpmem[8] = state->S_44_32[0];
+ tmpmem[9] = state->S_44_32[1];
+ tmpmem[10] = state->S_44_32[2];
+ tmpmem[11] = state->S_44_32[3];
+ tmpmem[12] = state->S_44_32[4];
+ tmpmem[13] = state->S_44_32[5];
+ tmpmem[14] = state->S_44_32[6];
+ tmpmem[15] = state->S_44_32[7];
+ state->S_44_32[0] = tmpmem[440 / SUB_BLOCKS_22_16 + 8];
+ state->S_44_32[1] = tmpmem[440 / SUB_BLOCKS_22_16 + 9];
+ state->S_44_32[2] = tmpmem[440 / SUB_BLOCKS_22_16 + 10];
+ state->S_44_32[3] = tmpmem[440 / SUB_BLOCKS_22_16 + 11];
+ state->S_44_32[4] = tmpmem[440 / SUB_BLOCKS_22_16 + 12];
+ state->S_44_32[5] = tmpmem[440 / SUB_BLOCKS_22_16 + 13];
+ state->S_44_32[6] = tmpmem[440 / SUB_BLOCKS_22_16 + 14];
+ state->S_44_32[7] = tmpmem[440 / SUB_BLOCKS_22_16 + 15];
+
+ WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 40 / SUB_BLOCKS_22_16);
+
+ ///// 32 --> 16 /////
+ // WebRtc_Word32 in[320/SUB_BLOCKS_22_16]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_22_16]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 320 / SUB_BLOCKS_22_16, out, state->S_32_16);
+
+ // move input/output pointers 10/SUB_BLOCKS_22_16 ms seconds ahead
+ in += 220 / SUB_BLOCKS_22_16;
+ out += 160 / SUB_BLOCKS_22_16;
+ }
+}
+
+// initialize state of 22 -> 16 resampler
+void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_22_44[k] = 0;
+ state->S_44_32[k] = 0;
+ state->S_32_16[k] = 0;
+ }
+}
+
+//////////////////////
+// 16 kHz -> 22 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 4, 5, 10
+#define SUB_BLOCKS_16_22 4
+
+// 16 -> 22 resampler
+void WebRtcSpl_Resample16khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo22khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_16_22 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_16_22; k++)
+ {
+ ///// 16 --> 32 /////
+ // WebRtc_Word16 in[160/SUB_BLOCKS_16_22]
+ // WebRtc_Word32 out[320/SUB_BLOCKS_16_22]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 160 / SUB_BLOCKS_16_22, tmpmem + 8, state->S_16_32);
+
+ ///// 32 --> 22 /////
+ // WebRtc_Word32 in[320/SUB_BLOCKS_16_22]
+ // WebRtc_Word32 out[220/SUB_BLOCKS_16_22]
+ /////
+ // copy state to and from input array
+ tmpmem[0] = state->S_32_22[0];
+ tmpmem[1] = state->S_32_22[1];
+ tmpmem[2] = state->S_32_22[2];
+ tmpmem[3] = state->S_32_22[3];
+ tmpmem[4] = state->S_32_22[4];
+ tmpmem[5] = state->S_32_22[5];
+ tmpmem[6] = state->S_32_22[6];
+ tmpmem[7] = state->S_32_22[7];
+ state->S_32_22[0] = tmpmem[320 / SUB_BLOCKS_16_22];
+ state->S_32_22[1] = tmpmem[320 / SUB_BLOCKS_16_22 + 1];
+ state->S_32_22[2] = tmpmem[320 / SUB_BLOCKS_16_22 + 2];
+ state->S_32_22[3] = tmpmem[320 / SUB_BLOCKS_16_22 + 3];
+ state->S_32_22[4] = tmpmem[320 / SUB_BLOCKS_16_22 + 4];
+ state->S_32_22[5] = tmpmem[320 / SUB_BLOCKS_16_22 + 5];
+ state->S_32_22[6] = tmpmem[320 / SUB_BLOCKS_16_22 + 6];
+ state->S_32_22[7] = tmpmem[320 / SUB_BLOCKS_16_22 + 7];
+
+ WebRtcSpl_32khzTo22khzIntToShort(tmpmem, out, 20 / SUB_BLOCKS_16_22);
+
+ // move input/output pointers 10/SUB_BLOCKS_16_22 ms seconds ahead
+ in += 160 / SUB_BLOCKS_16_22;
+ out += 220 / SUB_BLOCKS_16_22;
+ }
+}
+
+// initialize state of 16 -> 22 resampler
+void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_16_32[k] = 0;
+ state->S_32_22[k] = 0;
+ }
+}
+
+//////////////////////
+// 22 kHz -> 8 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 5, 10
+#define SUB_BLOCKS_22_8 2
+
+// 22 -> 8 resampler
+void WebRtcSpl_Resample22khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo8khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_22_8 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_22_8; k++)
+ {
+ ///// 22 --> 22 lowpass /////
+ // WebRtc_Word16 in[220/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[220/SUB_BLOCKS_22_8]
+ /////
+ WebRtcSpl_LPBy2ShortToInt(in, 220 / SUB_BLOCKS_22_8, tmpmem + 16, state->S_22_22);
+
+ ///// 22 --> 16 /////
+ // WebRtc_Word32 in[220/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_22_8]
+ /////
+ // copy state to and from input array
+ tmpmem[8] = state->S_22_16[0];
+ tmpmem[9] = state->S_22_16[1];
+ tmpmem[10] = state->S_22_16[2];
+ tmpmem[11] = state->S_22_16[3];
+ tmpmem[12] = state->S_22_16[4];
+ tmpmem[13] = state->S_22_16[5];
+ tmpmem[14] = state->S_22_16[6];
+ tmpmem[15] = state->S_22_16[7];
+ state->S_22_16[0] = tmpmem[220 / SUB_BLOCKS_22_8 + 8];
+ state->S_22_16[1] = tmpmem[220 / SUB_BLOCKS_22_8 + 9];
+ state->S_22_16[2] = tmpmem[220 / SUB_BLOCKS_22_8 + 10];
+ state->S_22_16[3] = tmpmem[220 / SUB_BLOCKS_22_8 + 11];
+ state->S_22_16[4] = tmpmem[220 / SUB_BLOCKS_22_8 + 12];
+ state->S_22_16[5] = tmpmem[220 / SUB_BLOCKS_22_8 + 13];
+ state->S_22_16[6] = tmpmem[220 / SUB_BLOCKS_22_8 + 14];
+ state->S_22_16[7] = tmpmem[220 / SUB_BLOCKS_22_8 + 15];
+
+ WebRtcSpl_Resample44khzTo32khz(tmpmem + 8, tmpmem, 20 / SUB_BLOCKS_22_8);
+
+ ///// 16 --> 8 /////
+ // WebRtc_Word32 in[160/SUB_BLOCKS_22_8]
+ // WebRtc_Word32 out[80/SUB_BLOCKS_22_8]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 160 / SUB_BLOCKS_22_8, out, state->S_16_8);
+
+ // move input/output pointers 10/SUB_BLOCKS_22_8 ms seconds ahead
+ in += 220 / SUB_BLOCKS_22_8;
+ out += 80 / SUB_BLOCKS_22_8;
+ }
+}
+
+// initialize state of 22 -> 8 resampler
+void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_22_22[k] = 0;
+ state->S_22_22[k + 8] = 0;
+ state->S_22_16[k] = 0;
+ state->S_16_8[k] = 0;
+ }
+}
+
+//////////////////////
+// 8 kHz -> 22 kHz //
+//////////////////////
+
+// number of subblocks; options: 1, 2, 5, 10
+#define SUB_BLOCKS_8_22 2
+
+// 8 -> 22 resampler
+void WebRtcSpl_Resample8khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo22khz* state, WebRtc_Word32* tmpmem)
+{
+ int k;
+
+ // process two blocks of 10/SUB_BLOCKS_8_22 ms (to reduce temp buffer size)
+ for (k = 0; k < SUB_BLOCKS_8_22; k++)
+ {
+ ///// 8 --> 16 /////
+ // WebRtc_Word16 in[80/SUB_BLOCKS_8_22]
+ // WebRtc_Word32 out[160/SUB_BLOCKS_8_22]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 80 / SUB_BLOCKS_8_22, tmpmem + 18, state->S_8_16);
+
+ ///// 16 --> 11 /////
+ // WebRtc_Word32 in[160/SUB_BLOCKS_8_22]
+ // WebRtc_Word32 out[110/SUB_BLOCKS_8_22]
+ /////
+ // copy state to and from input array
+ tmpmem[10] = state->S_16_11[0];
+ tmpmem[11] = state->S_16_11[1];
+ tmpmem[12] = state->S_16_11[2];
+ tmpmem[13] = state->S_16_11[3];
+ tmpmem[14] = state->S_16_11[4];
+ tmpmem[15] = state->S_16_11[5];
+ tmpmem[16] = state->S_16_11[6];
+ tmpmem[17] = state->S_16_11[7];
+ state->S_16_11[0] = tmpmem[160 / SUB_BLOCKS_8_22 + 10];
+ state->S_16_11[1] = tmpmem[160 / SUB_BLOCKS_8_22 + 11];
+ state->S_16_11[2] = tmpmem[160 / SUB_BLOCKS_8_22 + 12];
+ state->S_16_11[3] = tmpmem[160 / SUB_BLOCKS_8_22 + 13];
+ state->S_16_11[4] = tmpmem[160 / SUB_BLOCKS_8_22 + 14];
+ state->S_16_11[5] = tmpmem[160 / SUB_BLOCKS_8_22 + 15];
+ state->S_16_11[6] = tmpmem[160 / SUB_BLOCKS_8_22 + 16];
+ state->S_16_11[7] = tmpmem[160 / SUB_BLOCKS_8_22 + 17];
+
+ WebRtcSpl_32khzTo22khzIntToInt(tmpmem + 10, tmpmem, 10 / SUB_BLOCKS_8_22);
+
+ ///// 11 --> 22 /////
+ // WebRtc_Word32 in[110/SUB_BLOCKS_8_22]
+ // WebRtc_Word16 out[220/SUB_BLOCKS_8_22]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 110 / SUB_BLOCKS_8_22, out, state->S_11_22);
+
+ // move input/output pointers 10/SUB_BLOCKS_8_22 ms seconds ahead
+ in += 80 / SUB_BLOCKS_8_22;
+ out += 220 / SUB_BLOCKS_8_22;
+ }
+}
+
+// initialize state of 8 -> 22 resampler
+void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state)
+{
+ int k;
+ for (k = 0; k < 8; k++)
+ {
+ state->S_8_16[k] = 0;
+ state->S_16_11[k] = 0;
+ state->S_11_22[k] = 0;
+ }
+}
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_DotProdIntToInt(const WebRtc_Word32* in1, const WebRtc_Word32* in2,
+ const WebRtc_Word16* coef_ptr, WebRtc_Word32* out1,
+ WebRtc_Word32* out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ *out1 = tmp1 + coef * in1[8];
+ *out2 = tmp2 + coef * in2[-8];
+}
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_DotProdIntToShort(const WebRtc_Word32* in1, const WebRtc_Word32* in2,
+ const WebRtc_Word16* coef_ptr, WebRtc_Word16* out1,
+ WebRtc_Word16* out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ tmp1 += coef * in1[8];
+ tmp2 += coef * in2[-8];
+
+ // scale down, round and saturate
+ tmp1 >>= 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ tmp2 >>= 15;
+ if (tmp2 > (WebRtc_Word32)0x00007FFF)
+ tmp2 = 0x00007FFF;
+ if (tmp2 < (WebRtc_Word32)0xFFFF8000)
+ tmp2 = 0xFFFF8000;
+ *out1 = (WebRtc_Word16)tmp1;
+ *out2 = (WebRtc_Word16)tmp2;
+}
+
+// Resampling ratio: 11/16
+// input: WebRtc_Word32 (normalized, not saturated) :: size 16 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 11 * K
+// K: Number of blocks
+
+void WebRtcSpl_32khzTo22khzIntToInt(const WebRtc_Word32* In,
+ WebRtc_Word32* Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (16 input samples -> 11 output samples);
+ // process in sub blocks of size 16 samples.
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ // first output sample
+ Out[0] = ((WebRtc_Word32)In[3] << 15) + (1 << 14);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[0], &In[22], kCoefficients32To22[0], &Out[1], &Out[10]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[2], &In[20], kCoefficients32To22[1], &Out[2], &Out[9]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[3], &In[19], kCoefficients32To22[2], &Out[3], &Out[8]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[5], &In[17], kCoefficients32To22[3], &Out[4], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToInt(&In[6], &In[16], kCoefficients32To22[4], &Out[5], &Out[6]);
+
+ // update pointers
+ In += 16;
+ Out += 11;
+ }
+}
+
+// Resampling ratio: 11/16
+// input: WebRtc_Word32 (normalized, not saturated) :: size 16 * K
+// output: WebRtc_Word16 (saturated) :: size 11 * K
+// K: Number of blocks
+
+void WebRtcSpl_32khzTo22khzIntToShort(const WebRtc_Word32 *In,
+ WebRtc_Word16 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (16 input samples -> 11 output samples);
+ // process in sub blocks of size 16 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ // first output sample
+ tmp = In[3];
+ if (tmp > (WebRtc_Word32)0x00007FFF)
+ tmp = 0x00007FFF;
+ if (tmp < (WebRtc_Word32)0xFFFF8000)
+ tmp = 0xFFFF8000;
+ Out[0] = (WebRtc_Word16)tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[0], &In[22], kCoefficients32To22[0], &Out[1], &Out[10]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[2], &In[20], kCoefficients32To22[1], &Out[2], &Out[9]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[3], &In[19], kCoefficients32To22[2], &Out[3], &Out[8]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[5], &In[17], kCoefficients32To22[3], &Out[4], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_DotProdIntToShort(&In[6], &In[16], kCoefficients32To22[4], &Out[5], &Out[6]);
+
+ // update pointers
+ In += 16;
+ Out += 11;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/resample_48khz.c b/src/mod/codecs/mod_isac/resample_48khz.c
new file mode 100644
index 0000000000..31cbe6b6a9
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample_48khz.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains resampling functions between 48 kHz and nb/wb.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include
+#include "signal_processing_library.h"
+#include "resample_by_2_internal.h"
+
+////////////////////////////
+///// 48 kHz -> 16 kHz /////
+////////////////////////////
+
+// 48 -> 16 resampler
+void WebRtcSpl_Resample48khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo16khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 48 --> 48(LP) /////
+ // WebRtc_Word16 in[480]
+ // WebRtc_Word32 out[480]
+ /////
+ WebRtcSpl_LPBy2ShortToInt(in, 480, tmpmem + 16, state->S_48_48);
+
+ ///// 48 --> 32 /////
+ // WebRtc_Word32 in[480]
+ // WebRtc_Word32 out[320]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 8, state->S_48_32, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_48_32, tmpmem + 488, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 160);
+
+ ///// 32 --> 16 /////
+ // WebRtc_Word32 in[320]
+ // WebRtc_Word16 out[160]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 320, out, state->S_32_16);
+}
+
+// initialize state of 48 -> 16 resampler
+void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state)
+{
+ memset(state->S_48_48, 0, 16 * sizeof(WebRtc_Word32));
+ memset(state->S_48_32, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_32_16, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 16 kHz -> 48 kHz /////
+////////////////////////////
+
+// 16 -> 48 resampler
+void WebRtcSpl_Resample16khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo48khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 16 --> 32 /////
+ // WebRtc_Word16 in[160]
+ // WebRtc_Word32 out[320]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 160, tmpmem + 16, state->S_16_32);
+
+ ///// 32 --> 24 /////
+ // WebRtc_Word32 in[320]
+ // WebRtc_Word32 out[240]
+ // copy state to and from input array
+ /////
+ memcpy(tmpmem + 8, state->S_32_24, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_32_24, tmpmem + 328, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample32khzTo24khz(tmpmem + 8, tmpmem, 80);
+
+ ///// 24 --> 48 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word16 out[480]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
+}
+
+// initialize state of 16 -> 48 resampler
+void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state)
+{
+ memset(state->S_16_32, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_32_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 48 kHz -> 8 kHz /////
+////////////////////////////
+
+// 48 -> 8 resampler
+void WebRtcSpl_Resample48khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo8khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 48 --> 24 /////
+ // WebRtc_Word16 in[480]
+ // WebRtc_Word32 out[240]
+ /////
+ WebRtcSpl_DownBy2ShortToInt(in, 480, tmpmem + 256, state->S_48_24);
+
+ ///// 24 --> 24(LP) /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word32 out[240]
+ /////
+ WebRtcSpl_LPBy2IntToInt(tmpmem + 256, 240, tmpmem + 16, state->S_24_24);
+
+ ///// 24 --> 16 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word32 out[160]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 8, state->S_24_16, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_24_16, tmpmem + 248, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample48khzTo32khz(tmpmem + 8, tmpmem, 80);
+
+ ///// 16 --> 8 /////
+ // WebRtc_Word32 in[160]
+ // WebRtc_Word16 out[80]
+ /////
+ WebRtcSpl_DownBy2IntToShort(tmpmem, 160, out, state->S_16_8);
+}
+
+// initialize state of 48 -> 8 resampler
+void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state)
+{
+ memset(state->S_48_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_24, 0, 16 * sizeof(WebRtc_Word32));
+ memset(state->S_24_16, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_16_8, 0, 8 * sizeof(WebRtc_Word32));
+}
+
+////////////////////////////
+///// 8 kHz -> 48 kHz /////
+////////////////////////////
+
+// 8 -> 48 resampler
+void WebRtcSpl_Resample8khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo48khz* state, WebRtc_Word32* tmpmem)
+{
+ ///// 8 --> 16 /////
+ // WebRtc_Word16 in[80]
+ // WebRtc_Word32 out[160]
+ /////
+ WebRtcSpl_UpBy2ShortToInt(in, 80, tmpmem + 264, state->S_8_16);
+
+ ///// 16 --> 12 /////
+ // WebRtc_Word32 in[160]
+ // WebRtc_Word32 out[120]
+ /////
+ // copy state to and from input array
+ memcpy(tmpmem + 256, state->S_16_12, 8 * sizeof(WebRtc_Word32));
+ memcpy(state->S_16_12, tmpmem + 416, 8 * sizeof(WebRtc_Word32));
+ WebRtcSpl_Resample32khzTo24khz(tmpmem + 256, tmpmem + 240, 40);
+
+ ///// 12 --> 24 /////
+ // WebRtc_Word32 in[120]
+ // WebRtc_Word16 out[240]
+ /////
+ WebRtcSpl_UpBy2IntToInt(tmpmem + 240, 120, tmpmem, state->S_12_24);
+
+ ///// 24 --> 48 /////
+ // WebRtc_Word32 in[240]
+ // WebRtc_Word16 out[480]
+ /////
+ WebRtcSpl_UpBy2IntToShort(tmpmem, 240, out, state->S_24_48);
+}
+
+// initialize state of 8 -> 48 resampler
+void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state)
+{
+ memset(state->S_8_16, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_16_12, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_12_24, 0, 8 * sizeof(WebRtc_Word32));
+ memset(state->S_24_48, 0, 8 * sizeof(WebRtc_Word32));
+}
diff --git a/src/mod/codecs/mod_isac/resample_by_2.c b/src/mod/codecs/mod_isac/resample_by_2.c
new file mode 100644
index 0000000000..e239db75c0
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample_by_2.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the resampling by two functions.
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+
+// allpass filter coefficients.
+static const WebRtc_UWord32 kResampleAllpass1[3] = {3284, 24441, 49528 << 15};
+static const WebRtc_UWord32 kResampleAllpass2[3] =
+ {12199, 37471 << 15, 60255 << 15};
+
+// Multiply two 32-bit values and accumulate to another input value.
+// Return: state + ((diff * tbl_value) >> 16)
+
+static __inline WebRtc_Word32 MUL_ACCUM_1(WebRtc_Word32 tbl_value,
+ WebRtc_Word32 diff,
+ WebRtc_Word32 state) {
+ WebRtc_Word32 result;
+ __asm__("smlawb %r0, %r1, %r2, %r3": "=r"(result): "r"(diff),
+ "r"(tbl_value), "r"(state));
+ return result;
+}
+
+// Multiply two 32-bit values and accumulate to another input value.
+// Return: Return: state + (((diff << 1) * tbl_value) >> 32)
+//
+// The reason to introduce this function is that, in case we can't use smlawb
+// instruction (in MUL_ACCUM_1) due to input value range, we can still use
+// smmla to save some cycles.
+
+static __inline WebRtc_Word32 MUL_ACCUM_2(WebRtc_Word32 tbl_value,
+ WebRtc_Word32 diff,
+ WebRtc_Word32 state) {
+ WebRtc_Word32 result;
+ __asm__("smmla %r0, %r1, %r2, %r3": "=r"(result): "r"(diff << 1),
+ "r"(tbl_value), "r"(state));
+ return result;
+}
+
+#else
+
+// allpass filter coefficients.
+static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528};
+static const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255};
+
+// Multiply a 32-bit value with a 16-bit value and accumulate to another input:
+#define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
+#define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c)
+
+#endif // WEBRTC_ARCH_ARM_V7A
+
+
+// decimator
+void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState) {
+ WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
+ WebRtc_Word16 i;
+
+ register WebRtc_Word32 state0 = filtState[0];
+ register WebRtc_Word32 state1 = filtState[1];
+ register WebRtc_Word32 state2 = filtState[2];
+ register WebRtc_Word32 state3 = filtState[3];
+ register WebRtc_Word32 state4 = filtState[4];
+ register WebRtc_Word32 state5 = filtState[5];
+ register WebRtc_Word32 state6 = filtState[6];
+ register WebRtc_Word32 state7 = filtState[7];
+
+ for (i = (len >> 1); i > 0; i--) {
+ // lower allpass filter
+ in32 = (WebRtc_Word32)(*in++) << 10;
+ diff = in32 - state1;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0);
+ state0 = in32;
+ diff = tmp1 - state2;
+ tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1);
+ state1 = tmp1;
+ diff = tmp2 - state3;
+ state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2);
+ state2 = tmp2;
+
+ // upper allpass filter
+ in32 = (WebRtc_Word32)(*in++) << 10;
+ diff = in32 - state5;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4);
+ state4 = in32;
+ diff = tmp1 - state6;
+ tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5);
+ state5 = tmp1;
+ diff = tmp2 - state7;
+ state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6);
+ state6 = tmp2;
+
+ // add two allpass outputs, divide by two and round
+ out32 = (state3 + state7 + 1024) >> 11;
+
+ // limit amplitude to prevent wrap-around, and write to output array
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+ }
+
+ filtState[0] = state0;
+ filtState[1] = state1;
+ filtState[2] = state2;
+ filtState[3] = state3;
+ filtState[4] = state4;
+ filtState[5] = state5;
+ filtState[6] = state6;
+ filtState[7] = state7;
+}
+
+
+void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState) {
+ WebRtc_Word32 tmp1, tmp2, diff, in32, out32;
+ WebRtc_Word16 i;
+
+ register WebRtc_Word32 state0 = filtState[0];
+ register WebRtc_Word32 state1 = filtState[1];
+ register WebRtc_Word32 state2 = filtState[2];
+ register WebRtc_Word32 state3 = filtState[3];
+ register WebRtc_Word32 state4 = filtState[4];
+ register WebRtc_Word32 state5 = filtState[5];
+ register WebRtc_Word32 state6 = filtState[6];
+ register WebRtc_Word32 state7 = filtState[7];
+
+ for (i = len; i > 0; i--) {
+ // lower allpass filter
+ in32 = (WebRtc_Word32)(*in++) << 10;
+ diff = in32 - state1;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0);
+ state0 = in32;
+ diff = tmp1 - state2;
+ tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1);
+ state1 = tmp1;
+ diff = tmp2 - state3;
+ state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2);
+ state2 = tmp2;
+
+ // round; limit amplitude to prevent wrap-around; write to output array
+ out32 = (state3 + 512) >> 10;
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+
+ // upper allpass filter
+ diff = in32 - state5;
+ tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4);
+ state4 = in32;
+ diff = tmp1 - state6;
+ tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5);
+ state5 = tmp1;
+ diff = tmp2 - state7;
+ state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6);
+ state6 = tmp2;
+
+ // round; limit amplitude to prevent wrap-around; write to output array
+ out32 = (state7 + 512) >> 10;
+ *out++ = WebRtcSpl_SatW32ToW16(out32);
+ }
+
+ filtState[0] = state0;
+ filtState[1] = state1;
+ filtState[2] = state2;
+ filtState[3] = state3;
+ filtState[4] = state4;
+ filtState[5] = state5;
+ filtState[6] = state6;
+ filtState[7] = state7;
+}
diff --git a/src/mod/codecs/mod_isac/resample_by_2_internal.c b/src/mod/codecs/mod_isac/resample_by_2_internal.c
new file mode 100644
index 0000000000..cbd2395803
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample_by_2_internal.c
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This header file contains some internal resampling functions.
+ *
+ */
+
+#include "resample_by_2_internal.h"
+
+// allpass filter coefficients.
+static const WebRtc_Word16 kResampleAllpass[2][3] = {
+ {821, 6110, 12382},
+ {3050, 9368, 15063}
+};
+
+//
+// decimator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) OVERWRITTEN!
+// output: WebRtc_Word16 (saturated) (of length len/2)
+// state: filter state array; length = 8
+
+void WebRtcSpl_DownBy2IntToShort(WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter (operates on even input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // divide by two and store temporarily
+ in[i << 1] = (state[3] >> 1);
+ }
+
+ in++;
+
+ // upper allpass filter (operates on odd input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // divide by two and store temporarily
+ in[i << 1] = (state[7] >> 1);
+ }
+
+ in--;
+
+ // combine allpass outputs
+ for (i = 0; i < len; i += 2)
+ {
+ // divide by two, add both allpass outputs and round
+ tmp0 = (in[i << 1] + in[(i << 1) + 1]) >> 15;
+ tmp1 = (in[(i << 1) + 2] + in[(i << 1) + 3]) >> 15;
+ if (tmp0 > (WebRtc_Word32)0x00007FFF)
+ tmp0 = 0x00007FFF;
+ if (tmp0 < (WebRtc_Word32)0xFFFF8000)
+ tmp0 = 0xFFFF8000;
+ out[i] = (WebRtc_Word16)tmp0;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i + 1] = (WebRtc_Word16)tmp1;
+ }
+}
+
+//
+// decimator
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) (of length len/2)
+// state: filter state array; length = 8
+
+void WebRtcSpl_DownBy2ShortToInt(const WebRtc_Word16 *in,
+ WebRtc_Word32 len,
+ WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter (operates on even input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // divide by two and store temporarily
+ out[i] = (state[3] >> 1);
+ }
+
+ in++;
+
+ // upper allpass filter (operates on odd input samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // divide by two and store temporarily
+ out[i] += (state[7] >> 1);
+ }
+
+ in--;
+}
+
+//
+// interpolator
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (normalized, not saturated) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[7] >> 15;
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i] << 15) + (1 << 14);
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 15;
+ }
+}
+
+//
+// interpolator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2IntToInt(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[7];
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3];
+ }
+}
+
+//
+// interpolator
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word16 (saturated) (of length len*2)
+// state: filter state array; length = 8
+void WebRtcSpl_UpBy2IntToShort(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ // upper allpass filter (generates odd output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // scale down, saturate and store
+ tmp1 = state[7] >> 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i << 1] = (WebRtc_Word16)tmp1;
+ }
+
+ out++;
+
+ // lower allpass filter (generates even output samples)
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i];
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, saturate and store
+ tmp1 = state[3] >> 15;
+ if (tmp1 > (WebRtc_Word32)0x00007FFF)
+ tmp1 = 0x00007FFF;
+ if (tmp1 < (WebRtc_Word32)0xFFFF8000)
+ tmp1 = 0xFFFF8000;
+ out[i << 1] = (WebRtc_Word16)tmp1;
+ }
+}
+
+// lowpass filter
+// input: WebRtc_Word16
+// output: WebRtc_Word32 (normalized, not saturated)
+// state: filter state array; length = 8
+void WebRtcSpl_LPBy2ShortToInt(const WebRtc_Word16* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter: odd input -> even output samples
+ in++;
+ // initial state of polyphase delay element
+ tmp0 = state[12];
+ for (i = 0; i < len; i++)
+ {
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 1;
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ }
+ in--;
+
+ // upper allpass filter: even input -> even output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
+ }
+
+ // switch to odd output samples
+ out++;
+
+ // lower allpass filter: even input -> odd output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[9];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[8] + diff * kResampleAllpass[1][0];
+ state[8] = tmp0;
+ diff = tmp1 - state[10];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[9] + diff * kResampleAllpass[1][1];
+ state[9] = tmp1;
+ diff = tmp0 - state[11];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[11] = state[10] + diff * kResampleAllpass[1][2];
+ state[10] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[11] >> 1;
+ }
+
+ // upper allpass filter: odd input -> odd output samples
+ in++;
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = ((WebRtc_Word32)in[i << 1] << 15) + (1 << 14);
+ diff = tmp0 - state[13];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[12] + diff * kResampleAllpass[0][0];
+ state[12] = tmp0;
+ diff = tmp1 - state[14];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[13] + diff * kResampleAllpass[0][1];
+ state[13] = tmp1;
+ diff = tmp0 - state[15];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[15] = state[14] + diff * kResampleAllpass[0][2];
+ state[14] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
+ }
+}
+
+// lowpass filter
+// input: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384)
+// output: WebRtc_Word32 (normalized, not saturated)
+// state: filter state array; length = 8
+void WebRtcSpl_LPBy2IntToInt(const WebRtc_Word32* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state)
+{
+ WebRtc_Word32 tmp0, tmp1, diff;
+ WebRtc_Word32 i;
+
+ len >>= 1;
+
+ // lower allpass filter: odd input -> even output samples
+ in++;
+ // initial state of polyphase delay element
+ tmp0 = state[12];
+ for (i = 0; i < len; i++)
+ {
+ diff = tmp0 - state[1];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[0] + diff * kResampleAllpass[1][0];
+ state[0] = tmp0;
+ diff = tmp1 - state[2];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[1] + diff * kResampleAllpass[1][1];
+ state[1] = tmp1;
+ diff = tmp0 - state[3];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[3] = state[2] + diff * kResampleAllpass[1][2];
+ state[2] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[3] >> 1;
+ tmp0 = in[i << 1];
+ }
+ in--;
+
+ // upper allpass filter: even input -> even output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[5];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[4] + diff * kResampleAllpass[0][0];
+ state[4] = tmp0;
+ diff = tmp1 - state[6];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[5] + diff * kResampleAllpass[0][1];
+ state[5] = tmp1;
+ diff = tmp0 - state[7];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[7] = state[6] + diff * kResampleAllpass[0][2];
+ state[6] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[7] >> 1)) >> 15;
+ }
+
+ // switch to odd output samples
+ out++;
+
+ // lower allpass filter: even input -> odd output samples
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[9];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[8] + diff * kResampleAllpass[1][0];
+ state[8] = tmp0;
+ diff = tmp1 - state[10];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[9] + diff * kResampleAllpass[1][1];
+ state[9] = tmp1;
+ diff = tmp0 - state[11];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[11] = state[10] + diff * kResampleAllpass[1][2];
+ state[10] = tmp0;
+
+ // scale down, round and store
+ out[i << 1] = state[11] >> 1;
+ }
+
+ // upper allpass filter: odd input -> odd output samples
+ in++;
+ for (i = 0; i < len; i++)
+ {
+ tmp0 = in[i << 1];
+ diff = tmp0 - state[13];
+ // scale down and round
+ diff = (diff + (1 << 13)) >> 14;
+ tmp1 = state[12] + diff * kResampleAllpass[0][0];
+ state[12] = tmp0;
+ diff = tmp1 - state[14];
+ // scale down and round
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ tmp0 = state[13] + diff * kResampleAllpass[0][1];
+ state[13] = tmp1;
+ diff = tmp0 - state[15];
+ // scale down and truncate
+ diff = diff >> 14;
+ if (diff < 0)
+ diff += 1;
+ state[15] = state[14] + diff * kResampleAllpass[0][2];
+ state[14] = tmp0;
+
+ // average the two allpass outputs, scale down and store
+ out[i << 1] = (out[i << 1] + (state[15] >> 1)) >> 15;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/resample_by_2_internal.h b/src/mod/codecs/mod_isac/resample_by_2_internal.h
new file mode 100644
index 0000000000..b6ac9f0cb4
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample_by_2_internal.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This header file contains some internal resampling functions.
+ *
+ */
+
+#ifndef WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
+#define WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
+
+#include "typedefs.h"
+
+/*******************************************************************
+ * resample_by_2_fast.c
+ * Functions for internal use in the other resample functions
+ ******************************************************************/
+void WebRtcSpl_DownBy2IntToShort(WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word16 *out,
+ WebRtc_Word32 *state);
+
+void WebRtcSpl_DownBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len,
+ WebRtc_Word32 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2ShortToInt(const WebRtc_Word16 *in, WebRtc_Word32 len,
+ WebRtc_Word32 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2IntToInt(const WebRtc_Word32 *in, WebRtc_Word32 len, WebRtc_Word32 *out,
+ WebRtc_Word32 *state);
+
+void WebRtcSpl_UpBy2IntToShort(const WebRtc_Word32 *in, WebRtc_Word32 len,
+ WebRtc_Word16 *out, WebRtc_Word32 *state);
+
+void WebRtcSpl_LPBy2ShortToInt(const WebRtc_Word16* in, WebRtc_Word32 len,
+ WebRtc_Word32* out, WebRtc_Word32* state);
+
+void WebRtcSpl_LPBy2IntToInt(const WebRtc_Word32* in, WebRtc_Word32 len, WebRtc_Word32* out,
+ WebRtc_Word32* state);
+
+#endif // WEBRTC_SPL_RESAMPLE_BY_2_INTERNAL_H_
diff --git a/src/mod/codecs/mod_isac/resample_fractional.c b/src/mod/codecs/mod_isac/resample_fractional.c
new file mode 100644
index 0000000000..51003d45d7
--- /dev/null
+++ b/src/mod/codecs/mod_isac/resample_fractional.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the resampling functions between 48, 44, 32 and 24 kHz.
+ * The description headers can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// interpolation coefficients
+static const WebRtc_Word16 kCoefficients48To32[2][8] = {
+ {778, -2050, 1087, 23285, 12903, -3783, 441, 222},
+ {222, 441, -3783, 12903, 23285, 1087, -2050, 778}
+};
+
+static const WebRtc_Word16 kCoefficients32To24[3][8] = {
+ {767, -2362, 2434, 24406, 10620, -3838, 721, 90},
+ {386, -381, -2646, 19062, 19062, -2646, -381, 386},
+ {90, 721, -3838, 10620, 24406, 2434, -2362, 767}
+};
+
+static const WebRtc_Word16 kCoefficients44To32[4][9] = {
+ {117, -669, 2245, -6183, 26267, 13529, -3245, 845, -138},
+ {-101, 612, -2283, 8532, 29790, -5138, 1789, -524, 91},
+ {50, -292, 1016, -3064, 32010, 3933, -1147, 315, -53},
+ {-156, 974, -3863, 18603, 21691, -6246, 2353, -712, 126}
+};
+
+// Resampling ratio: 2/3
+// input: WebRtc_Word32 (normalized, not saturated) :: size 3 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 2 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample48khzTo32khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (3 input samples -> 2 output samples);
+ // process in sub blocks of size 3 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+ tmp += kCoefficients48To32[0][0] * In[0];
+ tmp += kCoefficients48To32[0][1] * In[1];
+ tmp += kCoefficients48To32[0][2] * In[2];
+ tmp += kCoefficients48To32[0][3] * In[3];
+ tmp += kCoefficients48To32[0][4] * In[4];
+ tmp += kCoefficients48To32[0][5] * In[5];
+ tmp += kCoefficients48To32[0][6] * In[6];
+ tmp += kCoefficients48To32[0][7] * In[7];
+ Out[0] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients48To32[1][0] * In[1];
+ tmp += kCoefficients48To32[1][1] * In[2];
+ tmp += kCoefficients48To32[1][2] * In[3];
+ tmp += kCoefficients48To32[1][3] * In[4];
+ tmp += kCoefficients48To32[1][4] * In[5];
+ tmp += kCoefficients48To32[1][5] * In[6];
+ tmp += kCoefficients48To32[1][6] * In[7];
+ tmp += kCoefficients48To32[1][7] * In[8];
+ Out[1] = tmp;
+
+ // update pointers
+ In += 3;
+ Out += 2;
+ }
+}
+
+// Resampling ratio: 3/4
+// input: WebRtc_Word32 (normalized, not saturated) :: size 4 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 3 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample32khzTo24khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (4 input samples -> 3 output samples);
+ // process in sub blocks of size 4 samples.
+ WebRtc_Word32 m;
+ WebRtc_Word32 tmp;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[0][0] * In[0];
+ tmp += kCoefficients32To24[0][1] * In[1];
+ tmp += kCoefficients32To24[0][2] * In[2];
+ tmp += kCoefficients32To24[0][3] * In[3];
+ tmp += kCoefficients32To24[0][4] * In[4];
+ tmp += kCoefficients32To24[0][5] * In[5];
+ tmp += kCoefficients32To24[0][6] * In[6];
+ tmp += kCoefficients32To24[0][7] * In[7];
+ Out[0] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[1][0] * In[1];
+ tmp += kCoefficients32To24[1][1] * In[2];
+ tmp += kCoefficients32To24[1][2] * In[3];
+ tmp += kCoefficients32To24[1][3] * In[4];
+ tmp += kCoefficients32To24[1][4] * In[5];
+ tmp += kCoefficients32To24[1][5] * In[6];
+ tmp += kCoefficients32To24[1][6] * In[7];
+ tmp += kCoefficients32To24[1][7] * In[8];
+ Out[1] = tmp;
+
+ tmp = 1 << 14;
+ tmp += kCoefficients32To24[2][0] * In[2];
+ tmp += kCoefficients32To24[2][1] * In[3];
+ tmp += kCoefficients32To24[2][2] * In[4];
+ tmp += kCoefficients32To24[2][3] * In[5];
+ tmp += kCoefficients32To24[2][4] * In[6];
+ tmp += kCoefficients32To24[2][5] * In[7];
+ tmp += kCoefficients32To24[2][6] * In[8];
+ tmp += kCoefficients32To24[2][7] * In[9];
+ Out[2] = tmp;
+
+ // update pointers
+ In += 4;
+ Out += 3;
+ }
+}
+
+//
+// fractional resampling filters
+// Fout = 11/16 * Fin
+// Fout = 8/11 * Fin
+//
+
+// compute two inner-products and store them to output array
+static void WebRtcSpl_ResampDotProduct(const WebRtc_Word32 *in1, const WebRtc_Word32 *in2,
+ const WebRtc_Word16 *coef_ptr, WebRtc_Word32 *out1,
+ WebRtc_Word32 *out2)
+{
+ WebRtc_Word32 tmp1 = 16384;
+ WebRtc_Word32 tmp2 = 16384;
+ WebRtc_Word16 coef;
+
+ coef = coef_ptr[0];
+ tmp1 += coef * in1[0];
+ tmp2 += coef * in2[-0];
+
+ coef = coef_ptr[1];
+ tmp1 += coef * in1[1];
+ tmp2 += coef * in2[-1];
+
+ coef = coef_ptr[2];
+ tmp1 += coef * in1[2];
+ tmp2 += coef * in2[-2];
+
+ coef = coef_ptr[3];
+ tmp1 += coef * in1[3];
+ tmp2 += coef * in2[-3];
+
+ coef = coef_ptr[4];
+ tmp1 += coef * in1[4];
+ tmp2 += coef * in2[-4];
+
+ coef = coef_ptr[5];
+ tmp1 += coef * in1[5];
+ tmp2 += coef * in2[-5];
+
+ coef = coef_ptr[6];
+ tmp1 += coef * in1[6];
+ tmp2 += coef * in2[-6];
+
+ coef = coef_ptr[7];
+ tmp1 += coef * in1[7];
+ tmp2 += coef * in2[-7];
+
+ coef = coef_ptr[8];
+ *out1 = tmp1 + coef * in1[8];
+ *out2 = tmp2 + coef * in2[-8];
+}
+
+// Resampling ratio: 8/11
+// input: WebRtc_Word32 (normalized, not saturated) :: size 11 * K
+// output: WebRtc_Word32 (shifted 15 positions to the left, + offset 16384) :: size 8 * K
+// K: number of blocks
+
+void WebRtcSpl_Resample44khzTo32khz(const WebRtc_Word32 *In, WebRtc_Word32 *Out,
+ const WebRtc_Word32 K)
+{
+ /////////////////////////////////////////////////////////////
+ // Filter operation:
+ //
+ // Perform resampling (11 input samples -> 8 output samples);
+ // process in sub blocks of size 11 samples.
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 m;
+
+ for (m = 0; m < K; m++)
+ {
+ tmp = 1 << 14;
+
+ // first output sample
+ Out[0] = ((WebRtc_Word32)In[3] << 15) + tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ tmp += kCoefficients44To32[3][0] * In[5];
+ tmp += kCoefficients44To32[3][1] * In[6];
+ tmp += kCoefficients44To32[3][2] * In[7];
+ tmp += kCoefficients44To32[3][3] * In[8];
+ tmp += kCoefficients44To32[3][4] * In[9];
+ tmp += kCoefficients44To32[3][5] * In[10];
+ tmp += kCoefficients44To32[3][6] * In[11];
+ tmp += kCoefficients44To32[3][7] * In[12];
+ tmp += kCoefficients44To32[3][8] * In[13];
+ Out[4] = tmp;
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[0], &In[17], kCoefficients44To32[0], &Out[1], &Out[7]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[2], &In[15], kCoefficients44To32[1], &Out[2], &Out[6]);
+
+ // sum and accumulate filter coefficients and input samples
+ WebRtcSpl_ResampDotProduct(&In[3], &In[14], kCoefficients44To32[2], &Out[3], &Out[5]);
+
+ // update pointers
+ In += 11;
+ Out += 8;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/settings.h b/src/mod/codecs/mod_isac/settings.h
new file mode 100644
index 0000000000..b7aed77065
--- /dev/null
+++ b/src/mod/codecs/mod_isac/settings.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * settings.h
+ *
+ * Declaration of #defines used in the iSAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_
+
+/* sampling frequency (Hz) */
+#define FS 16000
+
+/* number of samples per frame (either 320 (20ms), 480 (30ms) or 960 (60ms)) */
+#define INITIAL_FRAMESAMPLES 960
+
+
+#define MAXFFTSIZE 2048
+#define NFACTOR 11
+
+
+
+/* do not modify the following; this will have to be modified if we have a 20ms framesize option */
+/*************************************************************************************************/
+/* miliseconds */
+#define FRAMESIZE 30
+/* number of samples per frame processed in the encoder, 480 */
+#define FRAMESAMPLES 480 /* ((FRAMESIZE*FS)/1000) */
+#define FRAMESAMPLES_HALF 240
+#define FRAMESAMPLES_QUARTER 120
+/*************************************************************************************************/
+
+
+
+/* max number of samples per frame (= 60 ms frame) */
+#define MAX_FRAMESAMPLES 960
+#define MAX_SWBFRAMESAMPLES (MAX_FRAMESAMPLES * 2)
+/* number of samples per 10ms frame */
+#define FRAMESAMPLES_10ms ((10*FS)/1000)
+#define SWBFRAMESAMPLES_10ms (FRAMESAMPLES_10ms * 2)
+/* number of samples in 30 ms frame */
+#define FRAMESAMPLES_30ms 480
+/* number of subframes */
+#define SUBFRAMES 6
+/* length of a subframe */
+#define UPDATE 80
+/* length of half a subframe (low/high band) */
+#define HALF_SUBFRAMELEN (UPDATE/2)
+/* samples of look ahead (in a half-band, so actually half the samples of look ahead @ FS) */
+#define QLOOKAHEAD 24 /* 3 ms */
+/* order of AR model in spectral entropy coder */
+#define AR_ORDER 6
+/* order of LP model in spectral entropy coder */
+#define LP_ORDER 0
+
+/* window length (masking analysis) */
+#define WINLEN 256
+/* order of low-band pole filter used to approximate masking curve */
+#define ORDERLO 12
+/* order of hi-band pole filter used to approximate masking curve */
+#define ORDERHI 6
+
+#define UB_LPC_ORDER 4
+#define UB_LPC_VEC_PER_FRAME 2
+#define UB16_LPC_VEC_PER_FRAME 4
+#define UB_ACTIVE_SUBFRAMES 2
+#define UB_MAX_LPC_ORDER 6
+#define UB_INTERPOL_SEGMENTS 1
+#define UB16_INTERPOL_SEGMENTS 3
+#define LB_TOTAL_DELAY_SAMPLES 48
+enum ISACBandwidth {isac8kHz = 8, isac12kHz = 12, isac16kHz = 16};
+enum ISACBand{isacLowerBand = 0, isacUpperBand = 1};
+#define UB_LPC_GAIN_DIM SUBFRAMES
+#define FB_STATE_SIZE_WORD32 6
+
+
+/* order for post_filter_bank */
+#define POSTQORDER 3
+/* order for pre-filterbank */
+#define QORDER 3
+/* another order */
+#define QORDER_ALL (POSTQORDER+QORDER-1)
+/* for decimator */
+#define ALLPASSSECTIONS 2
+
+
+/* array size for byte stream in number of bytes. */
+#define STREAM_SIZE_MAX 600 /* The old maximum size still needed for the decoding */
+#define STREAM_SIZE_MAX_30 200 /* 200 bytes = 53.4 kbit/s @ 30 ms.framelength */
+#define STREAM_SIZE_MAX_60 400 /* 400 bytes = 53.4 kbit/s @ 60 ms.framelength */
+
+/* storage size for bit counts */
+#define BIT_COUNTER_SIZE 30
+/* maximum order of any AR model or filter */
+#define MAX_AR_MODEL_ORDER 12//50
+
+
+/* For pitch analysis */
+#define PITCH_FRAME_LEN (FRAMESAMPLES_HALF) /* 30 ms */
+#define PITCH_MAX_LAG 140 /* 57 Hz */
+#define PITCH_MIN_LAG 20 /* 400 Hz */
+#define PITCH_MAX_GAIN 0.45
+#define PITCH_MAX_GAIN_06 0.27 /* PITCH_MAX_GAIN*0.6 */
+#define PITCH_MAX_GAIN_Q12 1843
+#define PITCH_LAG_SPAN2 (PITCH_MAX_LAG/2-PITCH_MIN_LAG/2+5)
+#define PITCH_CORR_LEN2 60 /* 15 ms */
+#define PITCH_CORR_STEP2 (PITCH_FRAME_LEN/4)
+#define PITCH_BW 11 /* half the band width of correlation surface */
+#define PITCH_SUBFRAMES 4
+#define PITCH_GRAN_PER_SUBFRAME 5
+#define PITCH_SUBFRAME_LEN (PITCH_FRAME_LEN/PITCH_SUBFRAMES)
+#define PITCH_UPDATE (PITCH_SUBFRAME_LEN/PITCH_GRAN_PER_SUBFRAME)
+/* maximum number of peaks to be examined in correlation surface */
+#define PITCH_MAX_NUM_PEAKS 10
+#define PITCH_PEAK_DECAY 0.85
+/* For weighting filter */
+#define PITCH_WLPCORDER 6
+#define PITCH_WLPCWINLEN PITCH_FRAME_LEN
+#define PITCH_WLPCASYM 0.3 /* asymmetry parameter */
+#define PITCH_WLPCBUFLEN PITCH_WLPCWINLEN
+/* For pitch filter */
+#define PITCH_BUFFSIZE (PITCH_MAX_LAG + 50) /* Extra 50 for fraction and LP filters */
+#define PITCH_INTBUFFSIZE (PITCH_FRAME_LEN+PITCH_BUFFSIZE)
+/* Max rel. step for interpolation */
+#define PITCH_UPSTEP 1.5
+/* Max rel. step for interpolation */
+#define PITCH_DOWNSTEP 0.67
+#define PITCH_FRACS 8
+#define PITCH_FRACORDER 9
+#define PITCH_DAMPORDER 5
+#define PITCH_FILTDELAY 1.5f
+/* stepsize for quantization of the pitch Gain */
+#define PITCH_GAIN_STEPSIZE 0.125
+
+
+
+/* Order of high pass filter */
+#define HPORDER 2
+
+/* some mathematical constants */
+#define LOG2EXP 1.44269504088896 /* log2(exp) */
+#define PI 3.14159265358979
+
+/* Maximum number of iterations allowed to limit payload size */
+#define MAX_PAYLOAD_LIMIT_ITERATION 5
+
+/* Redundant Coding */
+#define RCU_BOTTLENECK_BPS 16000
+#define RCU_TRANSCODING_SCALE 0.40f
+#define RCU_TRANSCODING_SCALE_INVERSE 2.5f
+
+#define RCU_TRANSCODING_SCALE_UB 0.50f
+#define RCU_TRANSCODING_SCALE_UB_INVERSE 2.0f
+
+
+/* Define Error codes */
+/* 6000 General */
+#define ISAC_MEMORY_ALLOCATION_FAILED 6010
+#define ISAC_MODE_MISMATCH 6020
+#define ISAC_DISALLOWED_BOTTLENECK 6030
+#define ISAC_DISALLOWED_FRAME_LENGTH 6040
+#define ISAC_UNSUPPORTED_SAMPLING_FREQUENCY 6050
+
+/* 6200 Bandwidth estimator */
+#define ISAC_RANGE_ERROR_BW_ESTIMATOR 6240
+/* 6400 Encoder */
+#define ISAC_ENCODER_NOT_INITIATED 6410
+#define ISAC_DISALLOWED_CODING_MODE 6420
+#define ISAC_DISALLOWED_FRAME_MODE_ENCODER 6430
+#define ISAC_DISALLOWED_BITSTREAM_LENGTH 6440
+#define ISAC_PAYLOAD_LARGER_THAN_LIMIT 6450
+#define ISAC_DISALLOWED_ENCODER_BANDWIDTH 6460
+/* 6600 Decoder */
+#define ISAC_DECODER_NOT_INITIATED 6610
+#define ISAC_EMPTY_PACKET 6620
+#define ISAC_DISALLOWED_FRAME_MODE_DECODER 6630
+#define ISAC_RANGE_ERROR_DECODE_FRAME_LENGTH 6640
+#define ISAC_RANGE_ERROR_DECODE_BANDWIDTH 6650
+#define ISAC_RANGE_ERROR_DECODE_PITCH_GAIN 6660
+#define ISAC_RANGE_ERROR_DECODE_PITCH_LAG 6670
+#define ISAC_RANGE_ERROR_DECODE_LPC 6680
+#define ISAC_RANGE_ERROR_DECODE_SPECTRUM 6690
+#define ISAC_LENGTH_MISMATCH 6730
+#define ISAC_RANGE_ERROR_DECODE_BANDWITH 6740
+#define ISAC_DISALLOWED_BANDWIDTH_MODE_DECODER 6750
+/* 6800 Call setup formats */
+#define ISAC_INCOMPATIBLE_FORMATS 6810
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SETTINGS_H_ */
diff --git a/src/mod/codecs/mod_isac/signal_processing_library.h b/src/mod/codecs/mod_isac/signal_processing_library.h
new file mode 100644
index 0000000000..651a68c8b4
--- /dev/null
+++ b/src/mod/codecs/mod_isac/signal_processing_library.h
@@ -0,0 +1,1686 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This header file includes all of the fix point signal processing library (SPL) function
+ * descriptions and declarations.
+ * For specific function calls, see bottom of file.
+ */
+
+#ifndef WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+#define WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+
+#include
+#include "typedefs.h"
+
+#ifdef ARM_WINM
+#include // intrinsic file for windows mobile
+#endif
+
+// Macros specific for the fixed point implementation
+#define WEBRTC_SPL_WORD16_MAX 32767
+#define WEBRTC_SPL_WORD16_MIN -32768
+#define WEBRTC_SPL_WORD32_MAX (WebRtc_Word32)0x7fffffff
+#define WEBRTC_SPL_WORD32_MIN (WebRtc_Word32)0x80000000
+#define WEBRTC_SPL_MAX_LPC_ORDER 14
+#define WEBRTC_SPL_MAX_SEED_USED 0x80000000L
+#define WEBRTC_SPL_MIN(A, B) (A < B ? A : B) // Get min value
+#define WEBRTC_SPL_MAX(A, B) (A > B ? A : B) // Get max value
+#define WEBRTC_SPL_ABS_W16(a) \
+ (((WebRtc_Word16)a >= 0) ? ((WebRtc_Word16)a) : -((WebRtc_Word16)a))
+#define WEBRTC_SPL_ABS_W32(a) \
+ (((WebRtc_Word32)a >= 0) ? ((WebRtc_Word32)a) : -((WebRtc_Word32)a))
+
+#if (defined WEBRTC_TARGET_PC)||(defined __TARGET_XSCALE)
+#define WEBRTC_SPL_GET_BYTE(a, nr) (((WebRtc_Word8 *)a)[nr])
+#define WEBRTC_SPL_SET_BYTE(d_ptr, val, index) \
+ (((WebRtc_Word8 *)d_ptr)[index] = (val))
+#elif defined WEBRTC_BIG_ENDIAN
+#define WEBRTC_SPL_GET_BYTE(a, nr) \
+ ((((WebRtc_Word16 *)a)[nr >> 1]) >> (((nr + 1) & 0x1) * 8) & 0x00ff)
+#define WEBRTC_SPL_SET_BYTE(d_ptr, val, index) \
+ ((WebRtc_Word16 *)d_ptr)[index >> 1] = \
+ ((((WebRtc_Word16 *)d_ptr)[index >> 1]) \
+ & (0x00ff << (8 * ((index) & 0x1)))) | (val << (8 * ((index + 1) & 0x1)))
+#else
+#define WEBRTC_SPL_GET_BYTE(a,nr) \
+ ((((WebRtc_Word16 *)(a))[(nr) >> 1]) >> (((nr) & 0x1) * 8) & 0x00ff)
+#define WEBRTC_SPL_SET_BYTE(d_ptr, val, index) \
+ ((WebRtc_Word16 *)(d_ptr))[(index) >> 1] = \
+ ((((WebRtc_Word16 *)(d_ptr))[(index) >> 1]) \
+ & (0x00ff << (8 * (((index) + 1) & 0x1)))) | \
+ ((val) << (8 * ((index) & 0x1)))
+#endif
+
+#define WEBRTC_SPL_MUL(a, b) \
+ ((WebRtc_Word32) ((WebRtc_Word32)(a) * (WebRtc_Word32)(b)))
+#define WEBRTC_SPL_UMUL(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord32)(b)))
+#define WEBRTC_SPL_UMUL_RSFT16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord32)(b)) >> 16)
+#define WEBRTC_SPL_UMUL_16_16(a, b) \
+ ((WebRtc_UWord32) (WebRtc_UWord16)(a) * (WebRtc_UWord16)(b))
+#define WEBRTC_SPL_UMUL_16_16_RSFT16(a, b) \
+ (((WebRtc_UWord32) (WebRtc_UWord16)(a) * (WebRtc_UWord16)(b)) >> 16)
+#define WEBRTC_SPL_UMUL_32_16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord16)(b)))
+#define WEBRTC_SPL_UMUL_32_16_RSFT16(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) * (WebRtc_UWord16)(b)) >> 16)
+#define WEBRTC_SPL_MUL_16_U16(a, b) \
+ ((WebRtc_Word32)(WebRtc_Word16)(a) * (WebRtc_UWord16)(b))
+#define WEBRTC_SPL_DIV(a, b) \
+ ((WebRtc_Word32) ((WebRtc_Word32)(a) / (WebRtc_Word32)(b)))
+#define WEBRTC_SPL_UDIV(a, b) \
+ ((WebRtc_UWord32) ((WebRtc_UWord32)(a) / (WebRtc_UWord32)(b)))
+
+#ifndef WEBRTC_ARCH_ARM_V7A
+// For ARMv7 platforms, these are inline functions in spl_inl_armv7.h
+#define WEBRTC_SPL_MUL_16_16(a, b) \
+ ((WebRtc_Word32) (((WebRtc_Word16)(a)) * ((WebRtc_Word16)(b))))
+#define WEBRTC_SPL_MUL_16_32_RSFT16(a, b) \
+ (WEBRTC_SPL_MUL_16_16(a, b >> 16) \
+ + ((WEBRTC_SPL_MUL_16_16(a, (b & 0xffff) >> 1) + 0x4000) >> 15))
+#define WEBRTC_SPL_MUL_32_32_RSFT32(a32a, a32b, b32) \
+ ((WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT16(a32a, b32) \
+ + (WEBRTC_SPL_MUL_16_32_RSFT16(a32b, b32) >> 16)))
+#define WEBRTC_SPL_MUL_32_32_RSFT32BI(a32, b32) \
+ ((WebRtc_Word32)(WEBRTC_SPL_MUL_16_32_RSFT16(( \
+ (WebRtc_Word16)(a32 >> 16)), b32) + \
+ (WEBRTC_SPL_MUL_16_32_RSFT16(( \
+ (WebRtc_Word16)((a32 & 0x0000FFFF) >> 1)), b32) >> 15)))
+#endif
+
+#define WEBRTC_SPL_MUL_16_32_RSFT11(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 5) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x0200) >> 10))
+#define WEBRTC_SPL_MUL_16_32_RSFT14(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 2) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x1000) >> 13))
+#define WEBRTC_SPL_MUL_16_32_RSFT15(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, (b) >> 16) << 1) \
+ + (((WEBRTC_SPL_MUL_16_U16(a, (WebRtc_UWord16)(b)) >> 1) + 0x2000) >> 14))
+
+#ifdef ARM_WINM
+#define WEBRTC_SPL_MUL_16_16(a, b) \
+ _SmulLo_SW_SL((WebRtc_Word16)(a), (WebRtc_Word16)(b))
+#endif
+
+#define WEBRTC_SPL_MUL_16_16_RSFT(a, b, c) \
+ (WEBRTC_SPL_MUL_16_16(a, b) >> (c))
+
+#define WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(a, b, c) \
+ ((WEBRTC_SPL_MUL_16_16(a, b) + ((WebRtc_Word32) \
+ (((WebRtc_Word32)1) << ((c) - 1)))) >> (c))
+#define WEBRTC_SPL_MUL_16_16_RSFT_WITH_FIXROUND(a, b) \
+ ((WEBRTC_SPL_MUL_16_16(a, b) + ((WebRtc_Word32) (1 << 14))) >> 15)
+
+// C + the 32 most significant bits of A * B
+#define WEBRTC_SPL_SCALEDIFF32(A, B, C) \
+ (C + (B >> 16) * A + (((WebRtc_UWord32)(0x0000FFFF & B) * A) >> 16))
+
+#define WEBRTC_SPL_ADD_SAT_W32(a, b) WebRtcSpl_AddSatW32(a, b)
+#define WEBRTC_SPL_SAT(a, b, c) (b > a ? a : b < c ? c : b)
+#define WEBRTC_SPL_MUL_32_16(a, b) ((a) * (b))
+
+#define WEBRTC_SPL_SUB_SAT_W32(a, b) WebRtcSpl_SubSatW32(a, b)
+#define WEBRTC_SPL_ADD_SAT_W16(a, b) WebRtcSpl_AddSatW16(a, b)
+#define WEBRTC_SPL_SUB_SAT_W16(a, b) WebRtcSpl_SubSatW16(a, b)
+
+// We cannot do casting here due to signed/unsigned problem
+#define WEBRTC_SPL_IS_NEG(a) ((a) & 0x80000000)
+// Shifting with negative numbers allowed
+// Positive means left shift
+#define WEBRTC_SPL_SHIFT_W16(x, c) \
+ (((c) >= 0) ? ((x) << (c)) : ((x) >> (-(c))))
+#define WEBRTC_SPL_SHIFT_W32(x, c) \
+ (((c) >= 0) ? ((x) << (c)) : ((x) >> (-(c))))
+
+// Shifting with negative numbers not allowed
+// We cannot do casting here due to signed/unsigned problem
+#define WEBRTC_SPL_RSHIFT_W16(x, c) ((x) >> (c))
+#define WEBRTC_SPL_LSHIFT_W16(x, c) ((x) << (c))
+#define WEBRTC_SPL_RSHIFT_W32(x, c) ((x) >> (c))
+#define WEBRTC_SPL_LSHIFT_W32(x, c) ((x) << (c))
+
+#define WEBRTC_SPL_RSHIFT_U16(x, c) ((WebRtc_UWord16)(x) >> (c))
+#define WEBRTC_SPL_LSHIFT_U16(x, c) ((WebRtc_UWord16)(x) << (c))
+#define WEBRTC_SPL_RSHIFT_U32(x, c) ((WebRtc_UWord32)(x) >> (c))
+#define WEBRTC_SPL_LSHIFT_U32(x, c) ((WebRtc_UWord32)(x) << (c))
+
+#define WEBRTC_SPL_VNEW(t, n) (t *) malloc (sizeof (t) * (n))
+#define WEBRTC_SPL_FREE free
+
+#define WEBRTC_SPL_RAND(a) \
+ ((WebRtc_Word16)(WEBRTC_SPL_MUL_16_16_RSFT((a), 18816, 7) & 0x00007fff))
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define WEBRTC_SPL_MEMCPY_W8(v1, v2, length) \
+ memcpy(v1, v2, (length) * sizeof(char))
+#define WEBRTC_SPL_MEMCPY_W16(v1, v2, length) \
+ memcpy(v1, v2, (length) * sizeof(WebRtc_Word16))
+
+#define WEBRTC_SPL_MEMMOVE_W16(v1, v2, length) \
+ memmove(v1, v2, (length) * sizeof(WebRtc_Word16))
+
+// inline functions:
+#include "spl_inl.h"
+
+// Get SPL Version
+WebRtc_Word16 WebRtcSpl_get_version(char* version,
+ WebRtc_Word16 length_in_bytes);
+
+int WebRtcSpl_GetScalingSquare(WebRtc_Word16* in_vector,
+ int in_vector_length,
+ int times);
+
+// Copy and set operations. Implementation in copy_set_operations.c.
+// Descriptions at bottom of file.
+void WebRtcSpl_MemSetW16(WebRtc_Word16* vector,
+ WebRtc_Word16 set_value,
+ int vector_length);
+void WebRtcSpl_MemSetW32(WebRtc_Word32* vector,
+ WebRtc_Word32 set_value,
+ int vector_length);
+void WebRtcSpl_MemCpyReversedOrder(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ int vector_length);
+WebRtc_Word16 WebRtcSpl_CopyFromEndW16(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 samples,
+ WebRtc_Word16* out_vector);
+WebRtc_Word16 WebRtcSpl_ZerosArrayW16(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_ZerosArrayW32(WebRtc_Word32* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_OnesArrayW16(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length);
+WebRtc_Word16 WebRtcSpl_OnesArrayW32(WebRtc_Word32* vector,
+ WebRtc_Word16 vector_length);
+// End: Copy and set operations.
+
+// Minimum and maximum operations. Implementation in min_max_operations.c.
+// Descriptions at bottom of file.
+WebRtc_Word16 WebRtcSpl_MaxAbsValueW16(const WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+WebRtc_Word32 WebRtcSpl_MaxAbsValueW32(G_CONST WebRtc_Word32* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MinValueW16(G_CONST WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+WebRtc_Word32 WebRtcSpl_MinValueW32(G_CONST WebRtc_Word32* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MaxValueW16(G_CONST WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+
+WebRtc_Word16 WebRtcSpl_MaxAbsIndexW16(G_CONST WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+WebRtc_Word32 WebRtcSpl_MaxValueW32(G_CONST WebRtc_Word32* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MinIndexW16(G_CONST WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MinIndexW32(G_CONST WebRtc_Word32* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MaxIndexW16(G_CONST WebRtc_Word16* vector,
+ WebRtc_Word16 length);
+WebRtc_Word16 WebRtcSpl_MaxIndexW32(G_CONST WebRtc_Word32* vector,
+ WebRtc_Word16 length);
+// End: Minimum and maximum operations.
+
+// Vector scaling operations. Implementation in vector_scaling_operations.c.
+// Description at bottom of file.
+void WebRtcSpl_VectorBitShiftW16(WebRtc_Word16* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32* in_vector,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16* out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32* in_vector,
+ WebRtc_Word16 right_shifts);
+
+void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ScaleVectorWithSat(G_CONST WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ScaleAndAddVectors(G_CONST WebRtc_Word16* in_vector1,
+ WebRtc_Word16 gain1, int right_shifts1,
+ G_CONST WebRtc_Word16* in_vector2,
+ WebRtc_Word16 gain2, int right_shifts2,
+ WebRtc_Word16* out_vector,
+ int vector_length);
+// End: Vector scaling operations.
+
+// iLBC specific functions. Implementations in ilbc_specific_functions.c.
+// Description at bottom of file.
+void WebRtcSpl_ScaleAndAddVectorsWithRound(WebRtc_Word16* in_vector1,
+ WebRtc_Word16 scale1,
+ WebRtc_Word16* in_vector2,
+ WebRtc_Word16 scale2,
+ WebRtc_Word16 right_shifts,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 vector_length);
+void WebRtcSpl_ReverseOrderMultArrayElements(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector,
+ G_CONST WebRtc_Word16* window,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_ElementwiseVectorMult(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector,
+ G_CONST WebRtc_Word16* window,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_AddVectorsAndShift(WebRtc_Word16* out_vector,
+ G_CONST WebRtc_Word16* in_vector1,
+ G_CONST WebRtc_Word16* in_vector2,
+ WebRtc_Word16 vector_length,
+ WebRtc_Word16 right_shifts);
+void WebRtcSpl_AddAffineVectorToVector(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts,
+ int vector_length);
+void WebRtcSpl_AffineTransformVector(WebRtc_Word16* out_vector,
+ WebRtc_Word16* in_vector,
+ WebRtc_Word16 gain,
+ WebRtc_Word32 add_constant,
+ WebRtc_Word16 right_shifts,
+ int vector_length);
+// End: iLBC specific functions.
+
+// Signal processing operations. Descriptions at bottom of this file.
+int WebRtcSpl_AutoCorrelation(G_CONST WebRtc_Word16* vector,
+ int vector_length, int order,
+ WebRtc_Word32* result_vector,
+ int* scale);
+WebRtc_Word16 WebRtcSpl_LevinsonDurbin(WebRtc_Word32* auto_corr,
+ WebRtc_Word16* lpc_coef,
+ WebRtc_Word16* refl_coef,
+ WebRtc_Word16 order);
+void WebRtcSpl_ReflCoefToLpc(G_CONST WebRtc_Word16* refl_coef,
+ int use_order,
+ WebRtc_Word16* lpc_coef);
+void WebRtcSpl_LpcToReflCoef(WebRtc_Word16* lpc_coef,
+ int use_order,
+ WebRtc_Word16* refl_coef);
+void WebRtcSpl_AutoCorrToReflCoef(G_CONST WebRtc_Word32* auto_corr,
+ int use_order,
+ WebRtc_Word16* refl_coef);
+void WebRtcSpl_CrossCorrelation(WebRtc_Word32* cross_corr,
+ WebRtc_Word16* vector1,
+ WebRtc_Word16* vector2,
+ WebRtc_Word16 dim_vector,
+ WebRtc_Word16 dim_cross_corr,
+ WebRtc_Word16 right_shifts,
+ WebRtc_Word16 step_vector2);
+void WebRtcSpl_GetHanningWindow(WebRtc_Word16* window, WebRtc_Word16 size);
+void WebRtcSpl_SqrtOfOneMinusXSquared(WebRtc_Word16* in_vector,
+ int vector_length,
+ WebRtc_Word16* out_vector);
+// End: Signal processing operations.
+
+// Randomization functions. Implementations collected in randomization_functions.c and
+// descriptions at bottom of this file.
+WebRtc_UWord32 WebRtcSpl_IncreaseSeed(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandU(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandN(WebRtc_UWord32* seed);
+WebRtc_Word16 WebRtcSpl_RandUArray(WebRtc_Word16* vector,
+ WebRtc_Word16 vector_length,
+ WebRtc_UWord32* seed);
+// End: Randomization functions.
+
+// Math functions
+WebRtc_Word32 WebRtcSpl_Sqrt(WebRtc_Word32 value);
+WebRtc_Word32 WebRtcSpl_SqrtFloor(WebRtc_Word32 value);
+
+// Divisions. Implementations collected in division_operations.c and
+// descriptions at bottom of this file.
+WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den);
+WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den);
+WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den);
+WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den);
+WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
+ WebRtc_Word16 den_low);
+// End: Divisions.
+
+WebRtc_Word32 WebRtcSpl_Energy(WebRtc_Word16* vector,
+ int vector_length,
+ int* scale_factor);
+
+WebRtc_Word32 WebRtcSpl_DotProductWithScale(WebRtc_Word16* vector1,
+ WebRtc_Word16* vector2,
+ int vector_length,
+ int scaling);
+
+// Filter operations.
+int WebRtcSpl_FilterAR(G_CONST WebRtc_Word16* ar_coef, int ar_coef_length,
+ G_CONST WebRtc_Word16* in_vector, int in_vector_length,
+ WebRtc_Word16* filter_state, int filter_state_length,
+ WebRtc_Word16* filter_state_low,
+ int filter_state_low_length, WebRtc_Word16* out_vector,
+ WebRtc_Word16* out_vector_low, int out_vector_low_length);
+
+void WebRtcSpl_FilterMAFastQ12(WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16* ma_coef,
+ WebRtc_Word16 ma_coef_length,
+ WebRtc_Word16 vector_length);
+void WebRtcSpl_FilterARFastQ12(WebRtc_Word16* in_vector,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16* ar_coef,
+ WebRtc_Word16 ar_coef_length,
+ WebRtc_Word16 vector_length);
+int WebRtcSpl_DownsampleFast(WebRtc_Word16* in_vector,
+ WebRtc_Word16 in_vector_length,
+ WebRtc_Word16* out_vector,
+ WebRtc_Word16 out_vector_length,
+ WebRtc_Word16* ma_coef,
+ WebRtc_Word16 ma_coef_length,
+ WebRtc_Word16 factor,
+ WebRtc_Word16 delay);
+// End: Filter operations.
+
+// FFT operations
+int WebRtcSpl_ComplexFFT(WebRtc_Word16 vector[], int stages, int mode);
+int WebRtcSpl_ComplexIFFT(WebRtc_Word16 vector[], int stages, int mode);
+void WebRtcSpl_ComplexBitReverse(WebRtc_Word16 vector[], int stages);
+// End: FFT operations
+
+/************************************************************
+ *
+ * RESAMPLING FUNCTIONS AND THEIR STRUCTS ARE DEFINED BELOW
+ *
+ ************************************************************/
+
+/*******************************************************************
+ * resample.c
+ *
+ * Includes the following resampling combinations
+ * 22 kHz -> 16 kHz
+ * 16 kHz -> 22 kHz
+ * 22 kHz -> 8 kHz
+ * 8 kHz -> 22 kHz
+ *
+ ******************************************************************/
+
+// state structure for 22 -> 16 resampler
+typedef struct
+{
+ WebRtc_Word32 S_22_44[8];
+ WebRtc_Word32 S_44_32[8];
+ WebRtc_Word32 S_32_16[8];
+} WebRtcSpl_State22khzTo16khz;
+
+void WebRtcSpl_Resample22khzTo16khz(const WebRtc_Word16* in,
+ WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo16khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample22khzTo16khz(WebRtcSpl_State22khzTo16khz* state);
+
+// state structure for 16 -> 22 resampler
+typedef struct
+{
+ WebRtc_Word32 S_16_32[8];
+ WebRtc_Word32 S_32_22[8];
+} WebRtcSpl_State16khzTo22khz;
+
+void WebRtcSpl_Resample16khzTo22khz(const WebRtc_Word16* in,
+ WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo22khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample16khzTo22khz(WebRtcSpl_State16khzTo22khz* state);
+
+// state structure for 22 -> 8 resampler
+typedef struct
+{
+ WebRtc_Word32 S_22_22[16];
+ WebRtc_Word32 S_22_16[8];
+ WebRtc_Word32 S_16_8[8];
+} WebRtcSpl_State22khzTo8khz;
+
+void WebRtcSpl_Resample22khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State22khzTo8khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample22khzTo8khz(WebRtcSpl_State22khzTo8khz* state);
+
+// state structure for 8 -> 22 resampler
+typedef struct
+{
+ WebRtc_Word32 S_8_16[8];
+ WebRtc_Word32 S_16_11[8];
+ WebRtc_Word32 S_11_22[8];
+} WebRtcSpl_State8khzTo22khz;
+
+void WebRtcSpl_Resample8khzTo22khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo22khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample8khzTo22khz(WebRtcSpl_State8khzTo22khz* state);
+
+/*******************************************************************
+ * resample_fractional.c
+ * Functions for internal use in the other resample functions
+ *
+ * Includes the following resampling combinations
+ * 48 kHz -> 32 kHz
+ * 32 kHz -> 24 kHz
+ * 44 kHz -> 32 kHz
+ *
+ ******************************************************************/
+
+void WebRtcSpl_Resample48khzTo32khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_Resample32khzTo24khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+void WebRtcSpl_Resample44khzTo32khz(const WebRtc_Word32* In, WebRtc_Word32* Out,
+ const WebRtc_Word32 K);
+
+/*******************************************************************
+ * resample_48khz.c
+ *
+ * Includes the following resampling combinations
+ * 48 kHz -> 16 kHz
+ * 16 kHz -> 48 kHz
+ * 48 kHz -> 8 kHz
+ * 8 kHz -> 48 kHz
+ *
+ ******************************************************************/
+
+typedef struct
+{
+ WebRtc_Word32 S_48_48[16];
+ WebRtc_Word32 S_48_32[8];
+ WebRtc_Word32 S_32_16[8];
+} WebRtcSpl_State48khzTo16khz;
+
+void WebRtcSpl_Resample48khzTo16khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo16khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample48khzTo16khz(WebRtcSpl_State48khzTo16khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_16_32[8];
+ WebRtc_Word32 S_32_24[8];
+ WebRtc_Word32 S_24_48[8];
+} WebRtcSpl_State16khzTo48khz;
+
+void WebRtcSpl_Resample16khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State16khzTo48khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample16khzTo48khz(WebRtcSpl_State16khzTo48khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_48_24[8];
+ WebRtc_Word32 S_24_24[16];
+ WebRtc_Word32 S_24_16[8];
+ WebRtc_Word32 S_16_8[8];
+} WebRtcSpl_State48khzTo8khz;
+
+void WebRtcSpl_Resample48khzTo8khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State48khzTo8khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample48khzTo8khz(WebRtcSpl_State48khzTo8khz* state);
+
+typedef struct
+{
+ WebRtc_Word32 S_8_16[8];
+ WebRtc_Word32 S_16_12[8];
+ WebRtc_Word32 S_12_24[8];
+ WebRtc_Word32 S_24_48[8];
+} WebRtcSpl_State8khzTo48khz;
+
+void WebRtcSpl_Resample8khzTo48khz(const WebRtc_Word16* in, WebRtc_Word16* out,
+ WebRtcSpl_State8khzTo48khz* state,
+ WebRtc_Word32* tmpmem);
+
+void WebRtcSpl_ResetResample8khzTo48khz(WebRtcSpl_State8khzTo48khz* state);
+
+/*******************************************************************
+ * resample_by_2.c
+ *
+ * Includes down and up sampling by a factor of two.
+ *
+ ******************************************************************/
+
+void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len,
+ WebRtc_Word16* out, WebRtc_Word32* filtState);
+
+void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out,
+ WebRtc_Word32* filtState);
+
+/************************************************************
+ * END OF RESAMPLING FUNCTIONS
+ ************************************************************/
+void WebRtcSpl_AnalysisQMF(const WebRtc_Word16* in_data,
+ WebRtc_Word16* low_band,
+ WebRtc_Word16* high_band,
+ WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2);
+void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band,
+ const WebRtc_Word16* high_band,
+ WebRtc_Word16* out_data,
+ WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+#endif // WEBRTC_SPL_SIGNAL_PROCESSING_LIBRARY_H_
+
+//
+// WebRtcSpl_AddSatW16(...)
+// WebRtcSpl_AddSatW32(...)
+//
+// Returns the result of a saturated 16-bit, respectively 32-bit, addition of
+// the numbers specified by the |var1| and |var2| parameters.
+//
+// Input:
+// - var1 : Input variable 1
+// - var2 : Input variable 2
+//
+// Return value : Added and saturated value
+//
+
+//
+// WebRtcSpl_SubSatW16(...)
+// WebRtcSpl_SubSatW32(...)
+//
+// Returns the result of a saturated 16-bit, respectively 32-bit, subtraction
+// of the numbers specified by the |var1| and |var2| parameters.
+//
+// Input:
+// - var1 : Input variable 1
+// - var2 : Input variable 2
+//
+// Returned value : Subtracted and saturated value
+//
+
+//
+// WebRtcSpl_GetSizeInBits(...)
+//
+// Returns the # of bits that are needed at the most to represent the number
+// specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bits needed to represent |value|
+//
+
+//
+// WebRtcSpl_NormW32(...)
+//
+// Norm returns the # of left shifts required to 32-bit normalize the 32-bit
+// signed number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_NormW16(...)
+//
+// Norm returns the # of left shifts required to 16-bit normalize the 16-bit
+// signed number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_NormU32(...)
+//
+// Norm returns the # of left shifts required to 32-bit normalize the unsigned
+// 32-bit number specified by the |value| parameter.
+//
+// Input:
+// - value : Input value
+//
+// Return value : Number of bit shifts needed to 32-bit normalize |value|
+//
+
+//
+// WebRtcSpl_GetScalingSquare(...)
+//
+// Returns the # of bits required to scale the samples specified in the
+// |in_vector| parameter so that, if the squares of the samples are added the
+// # of times specified by the |times| parameter, the 32-bit addition will not
+// overflow (result in WebRtc_Word32).
+//
+// Input:
+// - in_vector : Input vector to check scaling on
+// - in_vector_length : Samples in |in_vector|
+// - times : Number of additions to be performed
+//
+// Return value : Number of right bit shifts needed to avoid
+// overflow in the addition calculation
+//
+
+//
+// WebRtcSpl_MemSetW16(...)
+//
+// Sets all the values in the WebRtc_Word16 vector |vector| of length
+// |vector_length| to the specified value |set_value|
+//
+// Input:
+// - vector : Pointer to the WebRtc_Word16 vector
+// - set_value : Value specified
+// - vector_length : Length of vector
+//
+
+//
+// WebRtcSpl_MemSetW32(...)
+//
+// Sets all the values in the WebRtc_Word32 vector |vector| of length
+// |vector_length| to the specified value |set_value|
+//
+// Input:
+// - vector : Pointer to the WebRtc_Word16 vector
+// - set_value : Value specified
+// - vector_length : Length of vector
+//
+
+//
+// WebRtcSpl_MemCpyReversedOrder(...)
+//
+// Copies all the values from the source WebRtc_Word16 vector |in_vector| to a
+// destination WebRtc_Word16 vector |out_vector|. It is done in reversed order,
+// meaning that the first sample of |in_vector| is copied to the last sample of
+// the |out_vector|. The procedure continues until the last sample of
+// |in_vector| has been copied to the first sample of |out_vector|. This
+// creates a reversed vector. Used in e.g. prediction in iLBC.
+//
+// Input:
+// - in_vector : Pointer to the first sample in a WebRtc_Word16 vector
+// of length |length|
+// - vector_length : Number of elements to copy
+//
+// Output:
+// - out_vector : Pointer to the last sample in a WebRtc_Word16 vector
+// of length |length|
+//
+
+//
+// WebRtcSpl_CopyFromEndW16(...)
+//
+// Copies the rightmost |samples| of |in_vector| (of length |in_vector_length|)
+// to the vector |out_vector|.
+//
+// Input:
+// - in_vector : Input vector
+// - in_vector_length : Number of samples in |in_vector|
+// - samples : Number of samples to extract (from right side)
+// from |in_vector|
+//
+// Output:
+// - out_vector : Vector with the requested samples
+//
+// Return value : Number of copied samples in |out_vector|
+//
+
+//
+// WebRtcSpl_ZerosArrayW16(...)
+// WebRtcSpl_ZerosArrayW32(...)
+//
+// Inserts the value "zero" in all positions of a w16 and a w32 vector
+// respectively.
+//
+// Input:
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - vector : Vector containing all zeros
+//
+// Return value : Number of samples in vector
+//
+
+//
+// WebRtcSpl_OnesArrayW16(...)
+// WebRtcSpl_OnesArrayW32(...)
+//
+// Inserts the value "one" in all positions of a w16 and a w32 vector
+// respectively.
+//
+// Input:
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - vector : Vector containing all ones
+//
+// Return value : Number of samples in vector
+//
+
+//
+// WebRtcSpl_MinValueW16(...)
+// WebRtcSpl_MinValueW32(...)
+//
+// Returns the minimum value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Minimum sample value in vector
+//
+
+//
+// WebRtcSpl_MaxValueW16(...)
+// WebRtcSpl_MaxValueW32(...)
+//
+// Returns the maximum value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Maximum sample value in vector
+//
+
+//
+// WebRtcSpl_MaxAbsValueW16(...)
+// WebRtcSpl_MaxAbsValueW32(...)
+//
+// Returns the largest absolute value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Maximum absolute value in vector
+//
+
+//
+// WebRtcSpl_MaxAbsIndexW16(...)
+//
+// Returns the vector index to the largest absolute value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Index to maximum absolute value in vector
+//
+
+//
+// WebRtcSpl_MinIndexW16(...)
+// WebRtcSpl_MinIndexW32(...)
+//
+// Returns the vector index to the minimum sample value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Index to minimum sample value in vector
+//
+
+//
+// WebRtcSpl_MaxIndexW16(...)
+// WebRtcSpl_MaxIndexW32(...)
+//
+// Returns the vector index to the maximum sample value of a vector
+//
+// Input:
+// - vector : Input vector
+// - vector_length : Number of samples in vector
+//
+// Return value : Index to maximum sample value in vector
+//
+
+//
+// WebRtcSpl_VectorBitShiftW16(...)
+// WebRtcSpl_VectorBitShiftW32(...)
+//
+// Bit shifts all the values in a vector up or downwards. Different calls for
+// WebRtc_Word16 and WebRtc_Word32 vectors respectively.
+//
+// Input:
+// - vector_length : Length of vector
+// - in_vector : Pointer to the vector that should be bit shifted
+// - right_shifts : Number of right bit shifts (negative value gives left
+// shifts)
+//
+// Output:
+// - out_vector : Pointer to the result vector (can be the same as
+// |in_vector|)
+//
+
+//
+// WebRtcSpl_VectorBitShiftW32ToW16(...)
+//
+// Bit shifts all the values in a WebRtc_Word32 vector up or downwards and
+// stores the result as a WebRtc_Word16 vector
+//
+// Input:
+// - vector_length : Length of vector
+// - in_vector : Pointer to the vector that should be bit shifted
+// - right_shifts : Number of right bit shifts (negative value gives left
+// shifts)
+//
+// Output:
+// - out_vector : Pointer to the result vector (can be the same as
+// |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleVector(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (gain*in_vector[k])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Scaling gain
+// - vector_length : Elements in the |in_vector|
+// - right_shifts : Number of right bit shifts applied
+//
+// Output:
+// - out_vector : Output vector (can be the same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleVectorWithSat(...)
+//
+// Performs the vector operation:
+// out_vector[k] = SATURATE( (gain*in_vector[k])>>right_shifts )
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Scaling gain
+// - vector_length : Elements in the |in_vector|
+// - right_shifts : Number of right bit shifts applied
+//
+// Output:
+// - out_vector : Output vector (can be the same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ScaleAndAddVectors(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (gain1*in_vector1[k])>>right_shifts1
+// + (gain2*in_vector2[k])>>right_shifts2
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - gain1 : Gain to be used for vector 1
+// - right_shifts1 : Right bit shift to be used for vector 1
+// - in_vector2 : Input vector 2
+// - gain2 : Gain to be used for vector 2
+// - right_shifts2 : Right bit shift to be used for vector 2
+// - vector_length : Elements in the input vectors
+//
+// Output:
+// - out_vector : Output vector
+//
+
+//
+// WebRtcSpl_ScaleAndAddVectorsWithRound(...)
+//
+// Performs the vector operation:
+//
+// out_vector[k] = ((scale1*in_vector1[k]) + (scale2*in_vector2[k])
+// + round_value) >> right_shifts
+//
+// where:
+//
+// round_value = (1<>1
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - scale1 : Gain to be used for vector 1
+// - in_vector2 : Input vector 2
+// - scale2 : Gain to be used for vector 2
+// - right_shifts : Number of right bit shifts to be applied
+// - vector_length : Number of elements in the input vectors
+//
+// Output:
+// - out_vector : Output vector
+//
+
+//
+// WebRtcSpl_ReverseOrderMultArrayElements(...)
+//
+// Performs the vector operation:
+// out_vector[n] = (in_vector[n]*window[-n])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - window : Window vector (should be reversed). The pointer
+// should be set to the last value in the vector
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector|)
+//
+
+//
+// WebRtcSpl_ElementwiseVectorMult(...)
+//
+// Performs the vector operation:
+// out_vector[n] = (in_vector[n]*window[n])>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - window : Window vector.
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector|)
+//
+
+//
+// WebRtcSpl_AddVectorsAndShift(...)
+//
+// Performs the vector operation:
+// out_vector[k] = (in_vector1[k] + in_vector2[k])>>right_shifts
+//
+// Input:
+// - in_vector1 : Input vector 1
+// - in_vector2 : Input vector 2
+// - right_shifts : Number of right bit shift to be applied after the
+// multiplication
+// - vector_length : Number of elements in |in_vector1| and |in_vector2|
+//
+// Output:
+// - out_vector : Output vector (can be same as |in_vector1|)
+//
+
+//
+// WebRtcSpl_AddAffineVectorToVector(...)
+//
+// Adds an affine transformed vector to another vector |out_vector|, i.e,
+// performs
+// out_vector[k] += (in_vector[k]*gain+add_constant)>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Gain value, used to multiply the in vector with
+// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
+// but others can be used as well
+// - right_shifts : Number of right bit shifts (0-16)
+// - vector_length : Number of samples in |in_vector| and |out_vector|
+//
+// Output:
+// - out_vector : Vector with the output
+//
+
+//
+// WebRtcSpl_AffineTransformVector(...)
+//
+// Affine transforms a vector, i.e, performs
+// out_vector[k] = (in_vector[k]*gain+add_constant)>>right_shifts
+//
+// Input:
+// - in_vector : Input vector
+// - gain : Gain value, used to multiply the in vector with
+// - add_constant : Constant value to add (usually 1<<(right_shifts-1),
+// but others can be used as well
+// - right_shifts : Number of right bit shifts (0-16)
+// - vector_length : Number of samples in |in_vector| and |out_vector|
+//
+// Output:
+// - out_vector : Vector with the output
+//
+
+//
+// WebRtcSpl_AutoCorrelation(...)
+//
+// A 32-bit fix-point implementation of auto-correlation computation
+//
+// Input:
+// - vector : Vector to calculate autocorrelation upon
+// - vector_length : Length (in samples) of |vector|
+// - order : The order up to which the autocorrelation should be
+// calculated
+//
+// Output:
+// - result_vector : auto-correlation values (values should be seen
+// relative to each other since the absolute values
+// might have been down shifted to avoid overflow)
+//
+// - scale : The number of left shifts required to obtain the
+// auto-correlation in Q0
+//
+// Return value : Number of samples in |result_vector|, i.e., (order+1)
+//
+
+//
+// WebRtcSpl_LevinsonDurbin(...)
+//
+// A 32-bit fix-point implementation of the Levinson-Durbin algorithm that
+// does NOT use the 64 bit class
+//
+// Input:
+// - auto_corr : Vector with autocorrelation values of length >=
+// |use_order|+1
+// - use_order : The LPC filter order (support up to order 20)
+//
+// Output:
+// - lpc_coef : lpc_coef[0..use_order] LPC coefficients in Q12
+// - refl_coef : refl_coef[0...use_order-1]| Reflection coefficients in
+// Q15
+//
+// Return value : 1 for stable 0 for unstable
+//
+
+//
+// WebRtcSpl_ReflCoefToLpc(...)
+//
+// Converts reflection coefficients |refl_coef| to LPC coefficients |lpc_coef|.
+// This version is a 16 bit operation.
+//
+// NOTE: The 16 bit refl_coef -> lpc_coef conversion might result in a
+// "slightly unstable" filter (i.e., a pole just outside the unit circle) in
+// "rare" cases even if the reflection coefficients are stable.
+//
+// Input:
+// - refl_coef : Reflection coefficients in Q15 that should be converted
+// to LPC coefficients
+// - use_order : Number of coefficients in |refl_coef|
+//
+// Output:
+// - lpc_coef : LPC coefficients in Q12
+//
+
+//
+// WebRtcSpl_LpcToReflCoef(...)
+//
+// Converts LPC coefficients |lpc_coef| to reflection coefficients |refl_coef|.
+// This version is a 16 bit operation.
+// The conversion is implemented by the step-down algorithm.
+//
+// Input:
+// - lpc_coef : LPC coefficients in Q12, that should be converted to
+// reflection coefficients
+// - use_order : Number of coefficients in |lpc_coef|
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
+//
+
+//
+// WebRtcSpl_AutoCorrToReflCoef(...)
+//
+// Calculates reflection coefficients (16 bit) from auto-correlation values
+//
+// Input:
+// - auto_corr : Auto-correlation values
+// - use_order : Number of coefficients wanted be calculated
+//
+// Output:
+// - refl_coef : Reflection coefficients in Q15.
+//
+
+//
+// WebRtcSpl_CrossCorrelation(...)
+//
+// Calculates the cross-correlation between two sequences |vector1| and
+// |vector2|. |vector1| is fixed and |vector2| slides as the pointer is
+// increased with the amount |step_vector2|
+//
+// Input:
+// - vector1 : First sequence (fixed throughout the correlation)
+// - vector2 : Second sequence (slides |step_vector2| for each
+// new correlation)
+// - dim_vector : Number of samples to use in the cross-correlation
+// - dim_cross_corr : Number of cross-correlations to calculate (the
+// start position for |vector2| is updated for each
+// new one)
+// - right_shifts : Number of right bit shifts to use. This will
+// become the output Q-domain.
+// - step_vector2 : How many (positive or negative) steps the
+// |vector2| pointer should be updated for each new
+// cross-correlation value.
+//
+// Output:
+// - cross_corr : The cross-correlation in Q(-right_shifts)
+//
+
+//
+// WebRtcSpl_GetHanningWindow(...)
+//
+// Creates (the first half of) a Hanning window. Size must be at least 1 and
+// at most 512.
+//
+// Input:
+// - size : Length of the requested Hanning window (1 to 512)
+//
+// Output:
+// - window : Hanning vector in Q14.
+//
+
+//
+// WebRtcSpl_SqrtOfOneMinusXSquared(...)
+//
+// Calculates y[k] = sqrt(1 - x[k]^2) for each element of the input vector
+// |in_vector|. Input and output values are in Q15.
+//
+// Inputs:
+// - in_vector : Values to calculate sqrt(1 - x^2) of
+// - vector_length : Length of vector |in_vector|
+//
+// Output:
+// - out_vector : Output values in Q15
+//
+
+//
+// WebRtcSpl_IncreaseSeed(...)
+//
+// Increases the seed (and returns the new value)
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : The new seed value
+//
+
+//
+// WebRtcSpl_RandU(...)
+//
+// Produces a uniformly distributed value in the WebRtc_Word16 range
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : Uniformly distributed value in the range
+// [Word16_MIN...Word16_MAX]
+//
+
+//
+// WebRtcSpl_RandN(...)
+//
+// Produces a normal distributed value in the WebRtc_Word16 range
+//
+// Input:
+// - seed : Seed for random calculation
+//
+// Output:
+// - seed : Updated seed value
+//
+// Return value : N(0,1) value in the Q13 domain
+//
+
+//
+// WebRtcSpl_RandUArray(...)
+//
+// Produces a uniformly distributed vector with elements in the WebRtc_Word16
+// range
+//
+// Input:
+// - vector_length : Samples wanted in the vector
+// - seed : Seed for random calculation
+//
+// Output:
+// - vector : Vector with the uniform values
+// - seed : Updated seed value
+//
+// Return value : Number of samples in vector, i.e., |vector_length|
+//
+
+//
+// WebRtcSpl_Sqrt(...)
+//
+// Returns the square root of the input value |value|. The precision of this
+// function is integer precision, i.e., sqrt(8) gives 2 as answer.
+// If |value| is a negative number then 0 is returned.
+//
+// Algorithm:
+//
+// A sixth order Taylor Series expansion is used here to compute the square
+// root of a number y^0.5 = (1+x)^0.5
+// where
+// x = y-1
+// = 1+(x/2)-0.5*((x/2)^2+0.5*((x/2)^3-0.625*((x/2)^4+0.875*((x/2)^5)
+// 0.5 <= x < 1
+//
+// Input:
+// - value : Value to calculate sqrt of
+//
+// Return value : Result of the sqrt calculation
+//
+
+//
+// WebRtcSpl_SqrtFloor(...)
+//
+// Returns the square root of the input value |value|. The precision of this
+// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
+// If |value| is a negative number then 0 is returned.
+//
+// Algorithm:
+//
+// An iterative 4 cylce/bit routine
+//
+// Input:
+// - value : Value to calculate sqrt of
+//
+// Return value : Result of the sqrt calculation
+//
+
+//
+// WebRtcSpl_DivU32U16(...)
+//
+// Divides a WebRtc_UWord32 |num| by a WebRtc_UWord16 |den|.
+//
+// If |den|==0, (WebRtc_UWord32)0xFFFFFFFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_UWord32), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivW32W16(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|.
+//
+// If |den|==0, (WebRtc_Word32)0x7FFFFFFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_Word32), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivW32W16ResW16(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|, assuming that the
+// result is less than 32768, otherwise an unpredictable result will occur.
+//
+// If |den|==0, (WebRtc_Word16)0x7FFF is returned.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division (as a WebRtc_Word16), i.e., the
+// integer part of num/den.
+//
+
+//
+// WebRtcSpl_DivResultInQ31(...)
+//
+// Divides a WebRtc_Word32 |num| by a WebRtc_Word16 |den|, assuming that the
+// absolute value of the denominator is larger than the numerator, otherwise
+// an unpredictable result will occur.
+//
+// Input:
+// - num : Numerator
+// - den : Denominator
+//
+// Return value : Result of the division in Q31.
+//
+
+//
+// WebRtcSpl_DivW32HiLow(...)
+//
+// Divides a WebRtc_Word32 |num| by a denominator in hi, low format. The
+// absolute value of the denominator has to be larger (or equal to) the
+// numerator.
+//
+// Input:
+// - num : Numerator
+// - den_hi : High part of denominator
+// - den_low : Low part of denominator
+//
+// Return value : Divided value in Q31
+//
+
+//
+// WebRtcSpl_Energy(...)
+//
+// Calculates the energy of a vector
+//
+// Input:
+// - vector : Vector which the energy should be calculated on
+// - vector_length : Number of samples in vector
+//
+// Output:
+// - scale_factor : Number of left bit shifts needed to get the physical
+// energy value, i.e, to get the Q0 value
+//
+// Return value : Energy value in Q(-|scale_factor|)
+//
+
+//
+// WebRtcSpl_FilterAR(...)
+//
+// Performs a 32-bit AR filtering on a vector in Q12
+//
+// Input:
+// - ar_coef : AR-coefficient vector (values in Q12),
+// ar_coef[0] must be 4096.
+// - ar_coef_length : Number of coefficients in |ar_coef|.
+// - in_vector : Vector to be filtered.
+// - in_vector_length : Number of samples in |in_vector|.
+// - filter_state : Current state (higher part) of the filter.
+// - filter_state_length : Length (in samples) of |filter_state|.
+// - filter_state_low : Current state (lower part) of the filter.
+// - filter_state_low_length : Length (in samples) of |filter_state_low|.
+// - out_vector_low_length : Maximum length (in samples) of
+// |out_vector_low|.
+//
+// Output:
+// - filter_state : Updated state (upper part) vector.
+// - filter_state_low : Updated state (lower part) vector.
+// - out_vector : Vector containing the upper part of the
+// filtered values.
+// - out_vector_low : Vector containing the lower part of the
+// filtered values.
+//
+// Return value : Number of samples in the |out_vector|.
+//
+
+//
+// WebRtcSpl_FilterMAFastQ12(...)
+//
+// Performs a MA filtering on a vector in Q12
+//
+// Input:
+// - in_vector : Input samples (state in positions
+// in_vector[-order] .. in_vector[-1])
+// - ma_coef : Filter coefficients (in Q12)
+// - ma_coef_length : Number of B coefficients (order+1)
+// - vector_length : Number of samples to be filtered
+//
+// Output:
+// - out_vector : Filtered samples
+//
+
+//
+// WebRtcSpl_FilterARFastQ12(...)
+//
+// Performs a AR filtering on a vector in Q12
+//
+// Input:
+// - in_vector : Input samples
+// - out_vector : State information in positions
+// out_vector[-order] .. out_vector[-1]
+// - ar_coef : Filter coefficients (in Q12)
+// - ar_coef_length : Number of B coefficients (order+1)
+// - vector_length : Number of samples to be filtered
+//
+// Output:
+// - out_vector : Filtered samples
+//
+
+//
+// WebRtcSpl_DownsampleFast(...)
+//
+// Performs a MA down sampling filter on a vector
+//
+// Input:
+// - in_vector : Input samples (state in positions
+// in_vector[-order] .. in_vector[-1])
+// - in_vector_length : Number of samples in |in_vector| to be filtered.
+// This must be at least
+// |delay| + |factor|*(|out_vector_length|-1) + 1)
+// - out_vector_length : Number of down sampled samples desired
+// - ma_coef : Filter coefficients (in Q12)
+// - ma_coef_length : Number of B coefficients (order+1)
+// - factor : Decimation factor
+// - delay : Delay of filter (compensated for in out_vector)
+//
+// Output:
+// - out_vector : Filtered samples
+//
+// Return value : 0 if OK, -1 if |in_vector| is too short
+//
+
+//
+// WebRtcSpl_DotProductWithScale(...)
+//
+// Calculates the dot product between two (WebRtc_Word16) vectors
+//
+// Input:
+// - vector1 : Vector 1
+// - vector2 : Vector 2
+// - vector_length : Number of samples used in the dot product
+// - scaling : The number of right bit shifts to apply on each term
+// during calculation to avoid overflow, i.e., the
+// output will be in Q(-|scaling|)
+//
+// Return value : The dot product in Q(-scaling)
+//
+
+//
+// WebRtcSpl_ComplexIFFT(...)
+//
+// Complex Inverse FFT
+//
+// Computes an inverse complex 2^|stages|-point FFT on the input vector, which
+// is in bit-reversed order. The original content of the vector is destroyed in
+// the process, since the input is overwritten by the output, normal-ordered,
+// FFT vector. With X as the input complex vector, y as the output complex
+// vector and with M = 2^|stages|, the following is computed:
+//
+// M-1
+// y(k) = sum[X(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
+// i=0
+//
+// The implementations are optimized for speed, not for code size. It uses the
+// decimation-in-time algorithm with radix-2 butterfly technique.
+//
+// Input:
+// - vector : In pointer to complex vector containing 2^|stages|
+// real elements interleaved with 2^|stages| imaginary
+// elements.
+// [ReImReImReIm....]
+// The elements are in Q(-scale) domain, see more on Return
+// Value below.
+//
+// - stages : Number of FFT stages. Must be at least 3 and at most 10,
+// since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// - mode : This parameter gives the user to choose how the FFT
+// should work.
+// mode==0: Low-complexity and Low-accuracy mode
+// mode==1: High-complexity and High-accuracy mode
+//
+// Output:
+// - vector : Out pointer to the FFT vector (the same as input).
+//
+// Return Value : The scale value that tells the number of left bit shifts
+// that the elements in the |vector| should be shifted with
+// in order to get Q0 values, i.e. the physically correct
+// values. The scale parameter is always 0 or positive,
+// except if N>1024 (|stages|>10), which returns a scale
+// value of -1, indicating error.
+//
+
+//
+// WebRtcSpl_ComplexFFT(...)
+//
+// Complex FFT
+//
+// Computes a complex 2^|stages|-point FFT on the input vector, which is in
+// bit-reversed order. The original content of the vector is destroyed in
+// the process, since the input is overwritten by the output, normal-ordered,
+// FFT vector. With x as the input complex vector, Y as the output complex
+// vector and with M = 2^|stages|, the following is computed:
+//
+// M-1
+// Y(k) = 1/M * sum[x(i)*[cos(2*pi*i*k/M) + j*sin(2*pi*i*k/M)]]
+// i=0
+//
+// The implementations are optimized for speed, not for code size. It uses the
+// decimation-in-time algorithm with radix-2 butterfly technique.
+//
+// This routine prevents overflow by scaling by 2 before each FFT stage. This is
+// a fixed scaling, for proper normalization - there will be log2(n) passes, so
+// this results in an overall factor of 1/n, distributed to maximize arithmetic
+// accuracy.
+//
+// Input:
+// - vector : In pointer to complex vector containing 2^|stages| real
+// elements interleaved with 2^|stages| imaginary elements.
+// [ReImReImReIm....]
+// The output is in the Q0 domain.
+//
+// - stages : Number of FFT stages. Must be at least 3 and at most 10,
+// since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// - mode : This parameter gives the user to choose how the FFT
+// should work.
+// mode==0: Low-complexity and Low-accuracy mode
+// mode==1: High-complexity and High-accuracy mode
+//
+// Output:
+// - vector : The output FFT vector is in the Q0 domain.
+//
+// Return value : The scale parameter is always 0, except if N>1024,
+// which returns a scale value of -1, indicating error.
+//
+
+//
+// WebRtcSpl_ComplexBitReverse(...)
+//
+// Complex Bit Reverse
+//
+// This function bit-reverses the position of elements in the complex input
+// vector into the output vector.
+//
+// If you bit-reverse a linear-order array, you obtain a bit-reversed order
+// array. If you bit-reverse a bit-reversed order array, you obtain a
+// linear-order array.
+//
+// Input:
+// - vector : In pointer to complex vector containing 2^|stages| real
+// elements interleaved with 2^|stages| imaginary elements.
+// [ReImReImReIm....]
+// - stages : Number of FFT stages. Must be at least 3 and at most 10,
+// since the table WebRtcSpl_kSinTable1024[] is 1024
+// elements long.
+//
+// Output:
+// - vector : Out pointer to complex vector in bit-reversed order.
+// The input vector is over written.
+//
+
+//
+// WebRtcSpl_AnalysisQMF(...)
+//
+// Splits a 0-2*F Hz signal into two sub bands: 0-F Hz and F-2*F Hz. The
+// current version has F = 8000, therefore, a super-wideband audio signal is
+// split to lower-band 0-8 kHz and upper-band 8-16 kHz.
+//
+// Input:
+// - in_data : Wide band speech signal, 320 samples (10 ms)
+//
+// Input & Output:
+// - filter_state1 : Filter state for first All-pass filter
+// - filter_state2 : Filter state for second All-pass filter
+//
+// Output:
+// - low_band : Lower-band signal 0-8 kHz band, 160 samples (10 ms)
+// - high_band : Upper-band signal 8-16 kHz band (flipped in frequency
+// domain), 160 samples (10 ms)
+//
+
+//
+// WebRtcSpl_SynthesisQMF(...)
+//
+// Combines the two sub bands (0-F and F-2*F Hz) into a signal of 0-2*F
+// Hz, (current version has F = 8000 Hz). So the filter combines lower-band
+// (0-8 kHz) and upper-band (8-16 kHz) channels to obtain super-wideband 0-16
+// kHz audio.
+//
+// Input:
+// - low_band : The signal with the 0-8 kHz band, 160 samples (10 ms)
+// - high_band : The signal with the 8-16 kHz band, 160 samples (10 ms)
+//
+// Input & Output:
+// - filter_state1 : Filter state for first All-pass filter
+// - filter_state2 : Filter state for second All-pass filter
+//
+// Output:
+// - out_data : Super-wideband speech signal, 0-16 kHz
+//
+
+// WebRtc_Word16 WebRtcSpl_SatW32ToW16(...)
+//
+// This function saturates a 32-bit word into a 16-bit word.
+//
+// Input:
+// - value32 : The value of a 32-bit word.
+//
+// Output:
+// - out16 : the saturated 16-bit word.
+//
+
+// int32_t WebRtc_MulAccumW16(...)
+//
+// This function multiply a 16-bit word by a 16-bit word, and accumulate this
+// value to a 32-bit integer.
+//
+// Input:
+// - a : The value of the first 16-bit word.
+// - b : The value of the second 16-bit word.
+// - c : The value of an 32-bit integer.
+//
+// Return Value: The value of a * b + c.
+//
+
+// WebRtc_Word16 WebRtcSpl_get_version(...)
+//
+// This function gives the version string of the Signal Processing Library.
+//
+// Input:
+// - length_in_bytes : The size of Allocated space (in Bytes) where
+// the version number is written to (in string format).
+//
+// Output:
+// - version : Pointer to a buffer where the version number is written to.
+//
diff --git a/src/mod/codecs/mod_isac/spectrum_ar_model_tables.c b/src/mod/codecs/mod_isac/spectrum_ar_model_tables.c
new file mode 100644
index 0000000000..92b9c4d626
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spectrum_ar_model_tables.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "spectrum_ar_model_tables.h"
+#include "settings.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc1Cdf[12] = {
+ 0, 2, 4, 129, 7707, 57485, 65495, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 2 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc2Cdf[12] = {
+ 0, 2, 4, 7, 531, 25298, 64525, 65526, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 3 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc3Cdf[12] = {
+ 0, 2, 4, 6, 620, 22898, 64843, 65527, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 4 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc4Cdf[12] = {
+ 0, 2, 4, 6, 35, 10034, 60733, 65506, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 5 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc5Cdf[12] = {
+ 0, 2, 4, 6, 36, 7567, 56727, 65385, 65529, 65531,
+ 65533, 65535};
+
+/* cdf for quantized reflection coefficient 6 */
+const WebRtc_UWord16 WebRtcIsac_kQArRc6Cdf[12] = {
+ 0, 2, 4, 6, 14, 6579, 57360, 65409, 65529, 65531,
+ 65533, 65535};
+
+/* representation levels for quantized reflection coefficient 1 */
+const WebRtc_Word16 WebRtcIsac_kQArRc1Levels[11] = {
+ -32104, -29007, -23202, -15496, -9279, -2577, 5934, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 2 */
+const WebRtc_Word16 WebRtcIsac_kQArRc2Levels[11] = {
+ -32104, -29503, -23494, -15261, -7309, -1399, 6158, 16381, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 3 */
+const WebRtc_Word16 WebRtcIsac_kQArRc3Levels[11] = {
+-32104, -29503, -23157, -15186, -7347, -1359, 5829, 17535, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 4 */
+const WebRtc_Word16 WebRtcIsac_kQArRc4Levels[11] = {
+-32104, -29503, -24512, -15362, -6665, -342, 6596, 14585, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 5 */
+const WebRtc_Word16 WebRtcIsac_kQArRc5Levels[11] = {
+-32104, -29503, -24512, -15005, -6564, -106, 7123, 14920, 24512, 29503, 32104
+};
+
+/* representation levels for quantized reflection coefficient 6 */
+const WebRtc_Word16 WebRtcIsac_kQArRc6Levels[11] = {
+-32104, -29503, -24512, -15096, -6656, -37, 7036, 14847, 24512, 29503, 32104
+};
+
+/* quantization boundary levels for reflection coefficients */
+const WebRtc_Word16 WebRtcIsac_kQArBoundaryLevels[12] = {
+-32768, -31441, -27566, -21458, -13612, -4663, 4663, 13612, 21458, 27566, 31441, 32767
+};
+
+/* initial index for AR reflection coefficient quantizer and cdf table search */
+const WebRtc_UWord16 WebRtcIsac_kQArRcInitIndex[6] = {
+ 5, 5, 5, 5, 5, 5};
+
+/* pointers to AR cdf tables */
+const WebRtc_UWord16 *WebRtcIsac_kQArRcCdfPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Cdf, WebRtcIsac_kQArRc2Cdf, WebRtcIsac_kQArRc3Cdf,
+ WebRtcIsac_kQArRc4Cdf, WebRtcIsac_kQArRc5Cdf, WebRtcIsac_kQArRc6Cdf
+};
+
+/* pointers to AR representation levels tables */
+const WebRtc_Word16 *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER] = {
+ WebRtcIsac_kQArRc1Levels, WebRtcIsac_kQArRc2Levels, WebRtcIsac_kQArRc3Levels,
+ WebRtcIsac_kQArRc4Levels, WebRtcIsac_kQArRc5Levels, WebRtcIsac_kQArRc6Levels
+};
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+const WebRtc_UWord16 WebRtcIsac_kQGainCdf[19] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 1172,
+ 11119, 29411, 51699, 64445, 65527, 65529, 65531, 65533, 65535};
+
+/* representation levels for quantized squared Gain coefficient */
+const WebRtc_Word32 WebRtcIsac_kQGain2Levels[18] = {
+// 17, 28, 46, 76, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+ 128, 128, 128, 128, 128, 215, 364, 709, 1268, 1960, 3405, 6078, 11286, 17827, 51918, 134498, 487432, 2048000};
+/* quantization boundary levels for squared Gain coefficient */
+const WebRtc_Word32 WebRtcIsac_kQGain2BoundaryLevels[19] = {
+0, 21, 35, 59, 99, 166, 280, 475, 815, 1414, 2495, 4505, 8397, 16405, 34431, 81359, 240497, 921600, 0x7FFFFFFF};
+
+/* pointers to Gain cdf table */
+const WebRtc_UWord16 *WebRtcIsac_kQGainCdf_ptr[1] = {WebRtcIsac_kQGainCdf};
+
+/* Gain initial index for gain quantizer and cdf table search */
+const WebRtc_UWord16 WebRtcIsac_kQGainInitIndex[1] = {11};
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+const WebRtc_Word16 WebRtcIsac_kCos[6][60] = {
+{512, 512, 511, 510, 508, 507, 505, 502, 499, 496, 493, 489, 485, 480, 476, 470, 465, 459, 453, 447,
+440, 433, 426, 418, 410, 402, 394, 385, 376, 367, 357, 348, 338, 327, 317, 306, 295, 284, 273, 262,
+250, 238, 226, 214, 202, 190, 177, 165, 152, 139, 126, 113, 100, 87, 73, 60, 47, 33, 20, 7},
+{512, 510, 508, 503, 498, 491, 483, 473, 462, 450, 437, 422, 406, 389, 371, 352, 333, 312, 290, 268,
+244, 220, 196, 171, 145, 120, 93, 67, 40, 13, -13, -40, -67, -93, -120, -145, -171, -196, -220, -244,
+-268, -290, -312, -333, -352, -371, -389, -406, -422, -437, -450, -462, -473, -483, -491, -498, -503, -508, -510, -512},
+{512, 508, 502, 493, 480, 465, 447, 426, 402, 376, 348, 317, 284, 250, 214, 177, 139, 100, 60, 20,
+-20, -60, -100, -139, -177, -214, -250, -284, -317, -348, -376, -402, -426, -447, -465, -480, -493, -502, -508, -512,
+-512, -508, -502, -493, -480, -465, -447, -426, -402, -376, -348, -317, -284, -250, -214, -177, -139, -100, -60, -20},
+{511, 506, 495, 478, 456, 429, 398, 362, 322, 279, 232, 183, 133, 80, 27, -27, -80, -133, -183, -232,
+-279, -322, -362, -398, -429, -456, -478, -495, -506, -511, -511, -506, -495, -478, -456, -429, -398, -362, -322, -279,
+-232, -183, -133, -80, -27, 27, 80, 133, 183, 232, 279, 322, 362, 398, 429, 456, 478, 495, 506, 511},
+{511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33, -33, -100, -165, -226, -284, -338, -385, -426,
+-459, -485, -502, -511, -511, -502, -485, -459, -426, -385, -338, -284, -226, -165, -100, -33, 33, 100, 165, 226,
+284, 338, 385, 426, 459, 485, 502, 511, 511, 502, 485, 459, 426, 385, 338, 284, 226, 165, 100, 33},
+{510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510,
+-510, -498, -473, -437, -389, -333, -268, -196, -120, -40, 40, 120, 196, 268, 333, 389, 437, 473, 498, 510,
+510, 498, 473, 437, 389, 333, 268, 196, 120, 40, -40, -120, -196, -268, -333, -389, -437, -473, -498, -510}
+};
diff --git a/src/mod/codecs/mod_isac/spectrum_ar_model_tables.h b/src/mod/codecs/mod_isac/spectrum_ar_model_tables.h
new file mode 100644
index 0000000000..159245bd98
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spectrum_ar_model_tables.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * spectrum_ar_model_tables.h
+ *
+ * This file contains definitions of tables with AR coefficients,
+ * Gain coefficients and cosine tables.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
+
+#include "structs.h"
+
+/********************* AR Coefficient Tables ************************/
+/* cdf for quantized reflection coefficient 1 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc1Cdf[12];
+
+/* cdf for quantized reflection coefficient 2 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc2Cdf[12];
+
+/* cdf for quantized reflection coefficient 3 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc3Cdf[12];
+
+/* cdf for quantized reflection coefficient 4 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc4Cdf[12];
+
+/* cdf for quantized reflection coefficient 5 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc5Cdf[12];
+
+/* cdf for quantized reflection coefficient 6 */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRc6Cdf[12];
+
+/* quantization boundary levels for reflection coefficients */
+extern const WebRtc_Word16 WebRtcIsac_kQArBoundaryLevels[12];
+
+/* initial indices for AR reflection coefficient quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsac_kQArRcInitIndex[AR_ORDER];
+
+/* pointers to AR cdf tables */
+extern const WebRtc_UWord16 *WebRtcIsac_kQArRcCdfPtr[AR_ORDER];
+
+/* pointers to AR representation levels tables */
+extern const WebRtc_Word16 *WebRtcIsac_kQArRcLevelsPtr[AR_ORDER];
+
+
+/******************** GAIN Coefficient Tables ***********************/
+/* cdf for Gain coefficient */
+extern const WebRtc_UWord16 WebRtcIsac_kQGainCdf[19];
+
+/* representation levels for quantized Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsac_kQGain2Levels[18];
+
+/* squared quantization boundary levels for Gain coefficient */
+extern const WebRtc_Word32 WebRtcIsac_kQGain2BoundaryLevels[19];
+
+/* pointer to Gain cdf table */
+extern const WebRtc_UWord16 *WebRtcIsac_kQGainCdf_ptr[1];
+
+/* Gain initial index for gain quantizer and cdf table search */
+extern const WebRtc_UWord16 WebRtcIsac_kQGainInitIndex[1];
+
+/************************* Cosine Tables ****************************/
+/* Cosine table */
+extern const WebRtc_Word16 WebRtcIsac_kCos[6][60];
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_ */
diff --git a/src/mod/codecs/mod_isac/spl_inl.h b/src/mod/codecs/mod_isac/spl_inl.h
new file mode 100644
index 0000000000..23b32099a3
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spl_inl.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+// This header file includes the inline functions in
+// the fix point signal processing library.
+
+#ifndef WEBRTC_SPL_SPL_INL_H_
+#define WEBRTC_SPL_SPL_INL_H_
+
+#ifdef WEBRTC_ARCH_ARM_V7A
+#include "spl_inl_armv7.h"
+#else
+
+static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
+ WebRtc_Word16 out16 = (WebRtc_Word16) value32;
+
+ if (value32 > 32767)
+ out16 = 32767;
+ else if (value32 < -32768)
+ out16 = -32768;
+
+ return out16;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ return WebRtcSpl_SatW32ToW16((WebRtc_Word32) a + (WebRtc_Word32) b);
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sum;
+
+ // perform long addition
+ l_sum = l_var1 + l_var2;
+
+ // check for under or overflow
+ if (WEBRTC_SPL_IS_NEG(l_var1)) {
+ if (WEBRTC_SPL_IS_NEG(l_var2) && !WEBRTC_SPL_IS_NEG(l_sum)) {
+ l_sum = (WebRtc_Word32)0x80000000;
+ }
+ } else {
+ if (!WEBRTC_SPL_IS_NEG(l_var2) && WEBRTC_SPL_IS_NEG(l_sum)) {
+ l_sum = (WebRtc_Word32)0x7FFFFFFF;
+ }
+ }
+
+ return l_sum;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
+ WebRtc_Word16 var2) {
+ return WebRtcSpl_SatW32ToW16((WebRtc_Word32) var1 - (WebRtc_Word32) var2);
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_diff;
+
+ // perform subtraction
+ l_diff = l_var1 - l_var2;
+
+ // check for underflow
+ if ((l_var1 < 0) && (l_var2 > 0) && (l_diff > 0))
+ l_diff = (WebRtc_Word32)0x80000000;
+ // check for overflow
+ if ((l_var1 > 0) && (l_var2 < 0) && (l_diff < 0))
+ l_diff = (WebRtc_Word32)0x7FFFFFFF;
+
+ return l_diff;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
+ int bits;
+
+ if (0xFFFF0000 & n) {
+ bits = 16;
+ } else {
+ bits = 0;
+ }
+ if (0x0000FF00 & (n >> bits)) bits += 8;
+ if (0x000000F0 & (n >> bits)) bits += 4;
+ if (0x0000000C & (n >> bits)) bits += 2;
+ if (0x00000002 & (n >> bits)) bits += 1;
+ if (0x00000001 & (n >> bits)) bits += 1;
+
+ return bits;
+}
+
+static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
+ int zeros;
+
+ if (a <= 0) a ^= 0xFFFFFFFF;
+
+ if (!(0xFFFF8000 & a)) {
+ zeros = 16;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xFF800000 & (a << zeros))) zeros += 8;
+ if (!(0xF8000000 & (a << zeros))) zeros += 4;
+ if (!(0xE0000000 & (a << zeros))) zeros += 2;
+ if (!(0xC0000000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
+ int zeros;
+
+ if (a == 0) return 0;
+
+ if (!(0xFFFF0000 & a)) {
+ zeros = 16;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xFF000000 & (a << zeros))) zeros += 8;
+ if (!(0xF0000000 & (a << zeros))) zeros += 4;
+ if (!(0xC0000000 & (a << zeros))) zeros += 2;
+ if (!(0x80000000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
+ int zeros;
+
+ if (a <= 0) a ^= 0xFFFF;
+
+ if (!(0xFF80 & a)) {
+ zeros = 8;
+ } else {
+ zeros = 0;
+ }
+ if (!(0xF800 & (a << zeros))) zeros += 4;
+ if (!(0xE000 & (a << zeros))) zeros += 2;
+ if (!(0xC000 & (a << zeros))) zeros += 1;
+
+ return zeros;
+}
+
+static __inline int32_t WebRtc_MulAccumW16(int16_t a,
+ int16_t b,
+ int32_t c) {
+ return (a * b + c);
+}
+
+#endif // WEBRTC_ARCH_ARM_V7A
+
+#endif // WEBRTC_SPL_SPL_INL_H_
diff --git a/src/mod/codecs/mod_isac/spl_inl_armv7.h b/src/mod/codecs/mod_isac/spl_inl_armv7.h
new file mode 100644
index 0000000000..689c2baeea
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spl_inl_armv7.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+// This header file includes the inline functions for ARM processors in
+// the fix point signal processing library.
+
+#ifndef WEBRTC_SPL_SPL_INL_ARMV7_H_
+#define WEBRTC_SPL_SPL_INL_ARMV7_H_
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_32_RSFT16(WebRtc_Word16 a,
+ WebRtc_Word32 b) {
+ WebRtc_Word32 tmp;
+ __asm__("smulwb %0, %1, %2":"=r"(tmp):"r"(b), "r"(a));
+ return tmp;
+}
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32(WebRtc_Word16 a,
+ WebRtc_Word16 b,
+ WebRtc_Word32 c) {
+ WebRtc_Word32 tmp;
+ __asm__("pkhbt %0, %1, %2, lsl #16" : "=r"(tmp) : "r"(b), "r"(a));
+ __asm__("smmul %0, %1, %2":"=r"(tmp):"r"(tmp), "r"(c));
+ return tmp;
+}
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_32_32_RSFT32BI(WebRtc_Word32 a,
+ WebRtc_Word32 b) {
+ WebRtc_Word32 tmp;
+ __asm__("smmul %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
+ return tmp;
+}
+
+static __inline WebRtc_Word32 WEBRTC_SPL_MUL_16_16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ WebRtc_Word32 tmp;
+ __asm__("smulbb %0, %1, %2":"=r"(tmp):"r"(a), "r"(b));
+ return tmp;
+}
+
+static __inline int32_t WebRtc_MulAccumW16(int16_t a,
+ int16_t b,
+ int32_t c) {
+ int32_t tmp = 0;
+ __asm__("smlabb %0, %1, %2, %3":"=r"(tmp):"r"(a), "r"(b), "r"(c));
+ return tmp;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_AddSatW16(WebRtc_Word16 a,
+ WebRtc_Word16 b) {
+ WebRtc_Word32 s_sum;
+
+ __asm__("qadd16 %0, %1, %2":"=r"(s_sum):"r"(a), "r"(b));
+
+ return (WebRtc_Word16) s_sum;
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_AddSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sum;
+
+ __asm__("qadd %0, %1, %2":"=r"(l_sum):"r"(l_var1), "r"(l_var2));
+
+ return l_sum;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_SubSatW16(WebRtc_Word16 var1,
+ WebRtc_Word16 var2) {
+ WebRtc_Word32 s_sub;
+
+ __asm__("qsub16 %0, %1, %2":"=r"(s_sub):"r"(var1), "r"(var2));
+
+ return (WebRtc_Word16)s_sub;
+}
+
+static __inline WebRtc_Word32 WebRtcSpl_SubSatW32(WebRtc_Word32 l_var1,
+ WebRtc_Word32 l_var2) {
+ WebRtc_Word32 l_sub;
+
+ __asm__("qsub %0, %1, %2":"=r"(l_sub):"r"(l_var1), "r"(l_var2));
+
+ return l_sub;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_GetSizeInBits(WebRtc_UWord32 n) {
+ WebRtc_Word32 tmp;
+
+ __asm__("clz %0, %1":"=r"(tmp):"r"(n));
+
+ return (WebRtc_Word16)(32 - tmp);
+}
+
+static __inline int WebRtcSpl_NormW32(WebRtc_Word32 a) {
+ WebRtc_Word32 tmp;
+
+ if (a <= 0) a ^= 0xFFFFFFFF;
+
+ __asm__("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp - 1;
+}
+
+static __inline int WebRtcSpl_NormU32(WebRtc_UWord32 a) {
+ int tmp;
+
+ if (a == 0) return 0;
+
+ __asm__("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp;
+}
+
+static __inline int WebRtcSpl_NormW16(WebRtc_Word16 a) {
+ WebRtc_Word32 tmp;
+
+ if (a <= 0) a ^= 0xFFFFFFFF;
+
+ __asm__("clz %0, %1":"=r"(tmp):"r"(a));
+
+ return tmp - 17;
+}
+
+static __inline WebRtc_Word16 WebRtcSpl_SatW32ToW16(WebRtc_Word32 value32) {
+ WebRtc_Word16 out16;
+
+ __asm__("ssat %r0, #16, %r1" : "=r"(out16) : "r"(value32));
+
+ return out16;
+}
+#endif // WEBRTC_SPL_SPL_INL_ARMV7_H_
diff --git a/src/mod/codecs/mod_isac/spl_sqrt.c b/src/mod/codecs/mod_isac/spl_sqrt.c
new file mode 100644
index 0000000000..cfe2cd3f34
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spl_sqrt.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_Sqrt().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+WebRtc_Word32 WebRtcSpl_SqrtLocal(WebRtc_Word32 in);
+
+WebRtc_Word32 WebRtcSpl_SqrtLocal(WebRtc_Word32 in)
+{
+
+ WebRtc_Word16 x_half, t16;
+ WebRtc_Word32 A, B, x2;
+
+ /* The following block performs:
+ y=in/2
+ x=y-2^30
+ x_half=x/2^31
+ t = 1 + (x_half) - 0.5*((x_half)^2) + 0.5*((x_half)^3) - 0.625*((x_half)^4)
+ + 0.875*((x_half)^5)
+ */
+
+ B = in;
+
+ B = WEBRTC_SPL_RSHIFT_W32(B, 1); // B = in/2
+ B = B - ((WebRtc_Word32)0x40000000); // B = in/2 - 1/2
+ x_half = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(B, 16);// x_half = x/2 = (in-1)/2
+ B = B + ((WebRtc_Word32)0x40000000); // B = 1 + x/2
+ B = B + ((WebRtc_Word32)0x40000000); // Add 0.5 twice (since 1.0 does not exist in Q31)
+
+ x2 = ((WebRtc_Word32)x_half) * ((WebRtc_Word32)x_half) * 2; // A = (x/2)^2
+ A = -x2; // A = -(x/2)^2
+ B = B + (A >> 1); // B = 1 + x/2 - 0.5*(x/2)^2
+
+ A = WEBRTC_SPL_RSHIFT_W32(A, 16);
+ A = A * A * 2; // A = (x/2)^4
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ B = B + WEBRTC_SPL_MUL_16_16(-20480, t16) * 2; // B = B - 0.625*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 - 0.625*(x/2)^4
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ A = WEBRTC_SPL_MUL_16_16(x_half, t16) * 2; // A = (x/2)^5
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16);
+ B = B + WEBRTC_SPL_MUL_16_16(28672, t16) * 2; // B = B + 0.875*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 - 0.625*(x/2)^4 + 0.875*(x/2)^5
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(x2, 16);
+ A = WEBRTC_SPL_MUL_16_16(x_half, t16) * 2; // A = x/2^3
+
+ B = B + (A >> 1); // B = B + 0.5*A
+ // After this, B = 1 + x/2 - 0.5*(x/2)^2 + 0.5*(x/2)^3 - 0.625*(x/2)^4 + 0.875*(x/2)^5
+
+ B = B + ((WebRtc_Word32)32768); // Round off bit
+
+ return B;
+}
+
+WebRtc_Word32 WebRtcSpl_Sqrt(WebRtc_Word32 value)
+{
+ /*
+ Algorithm:
+
+ Six term Taylor Series is used here to compute the square root of a number
+ y^0.5 = (1+x)^0.5 where x = y-1
+ = 1+(x/2)-0.5*((x/2)^2+0.5*((x/2)^3-0.625*((x/2)^4+0.875*((x/2)^5)
+ 0.5 <= x < 1
+
+ Example of how the algorithm works, with ut=sqrt(in), and
+ with in=73632 and ut=271 (even shift value case):
+
+ in=73632
+ y= in/131072
+ x=y-1
+ t = 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3) - 0.625*((x/2)^4) + 0.875*((x/2)^5)
+ ut=t*(1/sqrt(2))*512
+
+ or:
+
+ in=73632
+ in2=73632*2^14
+ y= in2/2^31
+ x=y-1
+ t = 1 + (x/2) - 0.5*((x/2)^2) + 0.5*((x/2)^3) - 0.625*((x/2)^4) + 0.875*((x/2)^5)
+ ut=t*(1/sqrt(2))
+ ut2=ut*2^9
+
+ which gives:
+
+ in = 73632
+ in2 = 1206386688
+ y = 0.56176757812500
+ x = -0.43823242187500
+ t = 0.74973506527313
+ ut = 0.53014274874797
+ ut2 = 2.714330873589594e+002
+
+ or:
+
+ in=73632
+ in2=73632*2^14
+ y=in2/2
+ x=y-2^30
+ x_half=x/2^31
+ t = 1 + (x_half) - 0.5*((x_half)^2) + 0.5*((x_half)^3) - 0.625*((x_half)^4)
+ + 0.875*((x_half)^5)
+ ut=t*(1/sqrt(2))
+ ut2=ut*2^9
+
+ which gives:
+
+ in = 73632
+ in2 = 1206386688
+ y = 603193344
+ x = -470548480
+ x_half = -0.21911621093750
+ t = 0.74973506527313
+ ut = 0.53014274874797
+ ut2 = 2.714330873589594e+002
+
+ */
+
+ WebRtc_Word16 x_norm, nshift, t16, sh;
+ WebRtc_Word32 A;
+
+ WebRtc_Word16 k_sqrt_2 = 23170; // 1/sqrt2 (==5a82)
+
+ A = value;
+
+ if (A == 0)
+ return (WebRtc_Word32)0; // sqrt(0) = 0
+
+ sh = WebRtcSpl_NormW32(A); // # shifts to normalize A
+ A = WEBRTC_SPL_LSHIFT_W32(A, sh); // Normalize A
+ if (A < (WEBRTC_SPL_WORD32_MAX - 32767))
+ {
+ A = A + ((WebRtc_Word32)32768); // Round off bit
+ } else
+ {
+ A = WEBRTC_SPL_WORD32_MAX;
+ }
+
+ x_norm = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16); // x_norm = AH
+
+ nshift = WEBRTC_SPL_RSHIFT_W16(sh, 1); // nshift = sh>>1
+ nshift = -nshift; // Negate the power for later de-normalization
+
+ A = (WebRtc_Word32)WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)x_norm, 16);
+ A = WEBRTC_SPL_ABS_W32(A); // A = abs(x_norm<<16)
+ A = WebRtcSpl_SqrtLocal(A); // A = sqrt(A)
+
+ if ((-2 * nshift) == sh)
+ { // Even shift value case
+
+ t16 = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(A, 16); // t16 = AH
+
+ A = WEBRTC_SPL_MUL_16_16(k_sqrt_2, t16) * 2; // A = 1/sqrt(2)*t16
+ A = A + ((WebRtc_Word32)32768); // Round off
+ A = A & ((WebRtc_Word32)0x7fff0000); // Round off
+
+ A = WEBRTC_SPL_RSHIFT_W32(A, 15); // A = A>>16
+
+ } else
+ {
+ A = WEBRTC_SPL_RSHIFT_W32(A, 16); // A = A>>16
+ }
+
+ A = A & ((WebRtc_Word32)0x0000ffff);
+ A = (WebRtc_Word32)WEBRTC_SPL_SHIFT_W32(A, nshift); // De-normalize the result
+
+ return A;
+}
diff --git a/src/mod/codecs/mod_isac/spl_sqrt_floor.c b/src/mod/codecs/mod_isac/spl_sqrt_floor.c
new file mode 100644
index 0000000000..aa36459ec4
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spl_sqrt_floor.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This file contains the function WebRtcSpl_SqrtFloor().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+#define WEBRTC_SPL_SQRT_ITER(N) \
+ try1 = root + (1 << (N)); \
+ if (value >= try1 << (N)) \
+ { \
+ value -= try1 << (N); \
+ root |= 2 << (N); \
+ }
+
+// (out) Square root of input parameter
+WebRtc_Word32 WebRtcSpl_SqrtFloor(WebRtc_Word32 value)
+{
+ // new routine for performance, 4 cycles/bit in ARM
+ // output precision is 16 bits
+
+ WebRtc_Word32 root = 0, try1;
+
+ WEBRTC_SPL_SQRT_ITER (15);
+ WEBRTC_SPL_SQRT_ITER (14);
+ WEBRTC_SPL_SQRT_ITER (13);
+ WEBRTC_SPL_SQRT_ITER (12);
+ WEBRTC_SPL_SQRT_ITER (11);
+ WEBRTC_SPL_SQRT_ITER (10);
+ WEBRTC_SPL_SQRT_ITER ( 9);
+ WEBRTC_SPL_SQRT_ITER ( 8);
+ WEBRTC_SPL_SQRT_ITER ( 7);
+ WEBRTC_SPL_SQRT_ITER ( 6);
+ WEBRTC_SPL_SQRT_ITER ( 5);
+ WEBRTC_SPL_SQRT_ITER ( 4);
+ WEBRTC_SPL_SQRT_ITER ( 3);
+ WEBRTC_SPL_SQRT_ITER ( 2);
+ WEBRTC_SPL_SQRT_ITER ( 1);
+ WEBRTC_SPL_SQRT_ITER ( 0);
+
+ return root >> 1;
+}
diff --git a/src/mod/codecs/mod_isac/spl_version.c b/src/mod/codecs/mod_isac/spl_version.c
new file mode 100644
index 0000000000..936925ea14
--- /dev/null
+++ b/src/mod/codecs/mod_isac/spl_version.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_get_version().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include
+#include "signal_processing_library.h"
+
+WebRtc_Word16 WebRtcSpl_get_version(char* version, WebRtc_Word16 length_in_bytes)
+{
+ strncpy(version, "1.2.0", length_in_bytes);
+ return 0;
+}
diff --git a/src/mod/codecs/mod_isac/splitting_filter.c b/src/mod/codecs/mod_isac/splitting_filter.c
new file mode 100644
index 0000000000..f1acf675f9
--- /dev/null
+++ b/src/mod/codecs/mod_isac/splitting_filter.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * This file contains the splitting filter functions.
+ *
+ */
+
+#include "signal_processing_library.h"
+
+// Number of samples in a low/high-band frame.
+enum
+{
+ kBandFrameLength = 160
+};
+
+// QMF filter coefficients in Q16.
+static const WebRtc_UWord16 WebRtcSpl_kAllPassFilter1[3] = {6418, 36982, 57261};
+static const WebRtc_UWord16 WebRtcSpl_kAllPassFilter2[3] = {21333, 49062, 63010};
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+// WebRtcSpl_AllPassQMF(...)
+//
+// Allpass filter used by the analysis and synthesis parts of the QMF filter.
+//
+// Input:
+// - in_data : Input data sequence (Q10)
+// - data_length : Length of data sequence (>2)
+// - filter_coefficients : Filter coefficients (length 3, Q16)
+//
+// Input & Output:
+// - filter_state : Filter state (length 6, Q10).
+//
+// Output:
+// - out_data : Output data sequence (Q10), length equal to
+// |data_length|
+//
+
+void WebRtcSpl_AllPassQMF(WebRtc_Word32* in_data, const WebRtc_Word16 data_length,
+ WebRtc_Word32* out_data, const WebRtc_UWord16* filter_coefficients,
+ WebRtc_Word32* filter_state)
+{
+ // The procedure is to filter the input with three first order all pass filters
+ // (cascade operations).
+ //
+ // a_3 + q^-1 a_2 + q^-1 a_1 + q^-1
+ // y[n] = ----------- ----------- ----------- x[n]
+ // 1 + a_3q^-1 1 + a_2q^-1 1 + a_1q^-1
+ //
+ // The input vector |filter_coefficients| includes these three filter coefficients.
+ // The filter state contains the in_data state, in_data[-1], followed by
+ // the out_data state, out_data[-1]. This is repeated for each cascade.
+ // The first cascade filter will filter the |in_data| and store the output in
+ // |out_data|. The second will the take the |out_data| as input and make an
+ // intermediate storage in |in_data|, to save memory. The third, and final, cascade
+ // filter operation takes the |in_data| (which is the output from the previous cascade
+ // filter) and store the output in |out_data|.
+ // Note that the input vector values are changed during the process.
+ WebRtc_Word16 k;
+ WebRtc_Word32 diff;
+ // First all-pass cascade; filter from in_data to out_data.
+
+ // Let y_i[n] indicate the output of cascade filter i (with filter coefficient a_i) at
+ // vector position n. Then the final output will be y[n] = y_3[n]
+
+ // First loop, use the states stored in memory.
+ // "diff" should be safe from wrap around since max values are 2^25
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[1]); // = (x[0] - y_1[-1])
+ // y_1[0] = x[-1] + a_1 * (x[0] - y_1[-1])
+ out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, filter_state[0]);
+
+ // For the remaining loops, use previous values.
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (x[n] - y_1[n-1])
+ // y_1[n] = x[n-1] + a_1 * (x[n] - y_1[n-1])
+ out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[0], diff, in_data[k - 1]);
+ }
+
+ // Update states.
+ filter_state[0] = in_data[data_length - 1]; // x[N-1], becomes x[-1] next time
+ filter_state[1] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
+
+ // Second all-pass cascade; filter from out_data to in_data.
+ diff = WEBRTC_SPL_SUB_SAT_W32(out_data[0], filter_state[3]); // = (y_1[0] - y_2[-1])
+ // y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
+ in_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, filter_state[2]);
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(out_data[k], in_data[k - 1]); // =(y_1[n] - y_2[n-1])
+ // y_2[0] = y_1[-1] + a_2 * (y_1[0] - y_2[-1])
+ in_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[1], diff, out_data[k-1]);
+ }
+
+ filter_state[2] = out_data[data_length - 1]; // y_1[N-1], becomes y_1[-1] next time
+ filter_state[3] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
+
+ // Third all-pass cascade; filter from in_data to out_data.
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[0], filter_state[5]); // = (y_2[0] - y[-1])
+ // y[0] = y_2[-1] + a_3 * (y_2[0] - y[-1])
+ out_data[0] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, filter_state[4]);
+ for (k = 1; k < data_length; k++)
+ {
+ diff = WEBRTC_SPL_SUB_SAT_W32(in_data[k], out_data[k - 1]); // = (y_2[n] - y[n-1])
+ // y[n] = y_2[n-1] + a_3 * (y_2[n] - y[n-1])
+ out_data[k] = WEBRTC_SPL_SCALEDIFF32(filter_coefficients[2], diff, in_data[k-1]);
+ }
+ filter_state[4] = in_data[data_length - 1]; // y_2[N-1], becomes y_2[-1] next time
+ filter_state[5] = out_data[data_length - 1]; // y[N-1], becomes y[-1] next time
+}
+
+void WebRtcSpl_AnalysisQMF(const WebRtc_Word16* in_data, WebRtc_Word16* low_band,
+ WebRtc_Word16* high_band, WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2)
+{
+ WebRtc_Word16 i;
+ WebRtc_Word16 k;
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 half_in1[kBandFrameLength];
+ WebRtc_Word32 half_in2[kBandFrameLength];
+ WebRtc_Word32 filter1[kBandFrameLength];
+ WebRtc_Word32 filter2[kBandFrameLength];
+
+ // Split even and odd samples. Also shift them to Q10.
+ for (i = 0, k = 0; i < kBandFrameLength; i++, k += 2)
+ {
+ half_in2[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)in_data[k], 10);
+ half_in1[i] = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)in_data[k + 1], 10);
+ }
+
+ // All pass filter even and odd samples, independently.
+ WebRtcSpl_AllPassQMF(half_in1, kBandFrameLength, filter1, WebRtcSpl_kAllPassFilter1,
+ filter_state1);
+ WebRtcSpl_AllPassQMF(half_in2, kBandFrameLength, filter2, WebRtcSpl_kAllPassFilter2,
+ filter_state2);
+
+ // Take the sum and difference of filtered version of odd and even
+ // branches to get upper & lower band.
+ for (i = 0; i < kBandFrameLength; i++)
+ {
+ tmp = filter1[i] + filter2[i] + 1024;
+ tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
+ low_band[i] = WebRtcSpl_SatW32ToW16(tmp);
+
+ tmp = filter1[i] - filter2[i] + 1024;
+ tmp = WEBRTC_SPL_RSHIFT_W32(tmp, 11);
+ high_band[i] = WebRtcSpl_SatW32ToW16(tmp);
+ }
+}
+
+void WebRtcSpl_SynthesisQMF(const WebRtc_Word16* low_band, const WebRtc_Word16* high_band,
+ WebRtc_Word16* out_data, WebRtc_Word32* filter_state1,
+ WebRtc_Word32* filter_state2)
+{
+ WebRtc_Word32 tmp;
+ WebRtc_Word32 half_in1[kBandFrameLength];
+ WebRtc_Word32 half_in2[kBandFrameLength];
+ WebRtc_Word32 filter1[kBandFrameLength];
+ WebRtc_Word32 filter2[kBandFrameLength];
+ WebRtc_Word16 i;
+ WebRtc_Word16 k;
+
+ // Obtain the sum and difference channels out of upper and lower-band channels.
+ // Also shift to Q10 domain.
+ for (i = 0; i < kBandFrameLength; i++)
+ {
+ tmp = (WebRtc_Word32)low_band[i] + (WebRtc_Word32)high_band[i];
+ half_in1[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
+ tmp = (WebRtc_Word32)low_band[i] - (WebRtc_Word32)high_band[i];
+ half_in2[i] = WEBRTC_SPL_LSHIFT_W32(tmp, 10);
+ }
+
+ // all-pass filter the sum and difference channels
+ WebRtcSpl_AllPassQMF(half_in1, kBandFrameLength, filter1, WebRtcSpl_kAllPassFilter2,
+ filter_state1);
+ WebRtcSpl_AllPassQMF(half_in2, kBandFrameLength, filter2, WebRtcSpl_kAllPassFilter1,
+ filter_state2);
+
+ // The filtered signals are even and odd samples of the output. Combine
+ // them. The signals are Q10 should shift them back to Q0 and take care of
+ // saturation.
+ for (i = 0, k = 0; i < kBandFrameLength; i++)
+ {
+ tmp = WEBRTC_SPL_RSHIFT_W32(filter2[i] + 512, 10);
+ out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
+
+ tmp = WEBRTC_SPL_RSHIFT_W32(filter1[i] + 512, 10);
+ out_data[k++] = WebRtcSpl_SatW32ToW16(tmp);
+ }
+
+}
diff --git a/src/mod/codecs/mod_isac/sqrt_of_one_minus_x_squared.c b/src/mod/codecs/mod_isac/sqrt_of_one_minus_x_squared.c
new file mode 100644
index 0000000000..9fb2c73bc5
--- /dev/null
+++ b/src/mod/codecs/mod_isac/sqrt_of_one_minus_x_squared.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the function WebRtcSpl_SqrtOfOneMinusXSquared().
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_SqrtOfOneMinusXSquared(WebRtc_Word16 *xQ15, int vector_length,
+ WebRtc_Word16 *yQ15)
+{
+ WebRtc_Word32 sq;
+ int m;
+ WebRtc_Word16 tmp;
+
+ for (m = 0; m < vector_length; m++)
+ {
+ tmp = xQ15[m];
+ sq = WEBRTC_SPL_MUL_16_16(tmp, tmp); // x^2 in Q30
+ sq = 1073741823 - sq; // 1-x^2, where 1 ~= 0.99999999906 is 1073741823 in Q30
+ sq = WebRtcSpl_Sqrt(sq); // sqrt(1-x^2) in Q15
+ yQ15[m] = (WebRtc_Word16)sq;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/structs.h b/src/mod/codecs/mod_isac/structs.h
new file mode 100644
index 0000000000..7523ad6e4a
--- /dev/null
+++ b/src/mod/codecs/mod_isac/structs.h
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+/*
+ * structs.h
+ *
+ * This header file contains all the structs used in the ISAC codec
+ *
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_
+
+
+#include "typedefs.h"
+#include "settings.h"
+#include "isac.h"
+
+typedef struct Bitstreamstruct {
+
+ WebRtc_UWord8 stream[STREAM_SIZE_MAX];
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 streamval;
+ WebRtc_UWord32 stream_index;
+
+} Bitstr;
+
+typedef struct {
+
+ double DataBufferLo[WINLEN];
+ double DataBufferHi[WINLEN];
+
+ double CorrBufLo[ORDERLO+1];
+ double CorrBufHi[ORDERHI+1];
+
+ float PreStateLoF[ORDERLO+1];
+ float PreStateLoG[ORDERLO+1];
+ float PreStateHiF[ORDERHI+1];
+ float PreStateHiG[ORDERHI+1];
+ float PostStateLoF[ORDERLO+1];
+ float PostStateLoG[ORDERLO+1];
+ float PostStateHiF[ORDERHI+1];
+ float PostStateHiG[ORDERHI+1];
+
+ double OldEnergy;
+
+} MaskFiltstr;
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+ double INSTAT1[2*(QORDER-1)];
+ double INSTAT2[2*(QORDER-1)];
+ double INSTATLA1[2*(QORDER-1)];
+ double INSTATLA2[2*(QORDER-1)];
+ double INLABUF1[QLOOKAHEAD];
+ double INLABUF2[QLOOKAHEAD];
+
+ float INSTAT1_float[2*(QORDER-1)];
+ float INSTAT2_float[2*(QORDER-1)];
+ float INSTATLA1_float[2*(QORDER-1)];
+ float INSTATLA2_float[2*(QORDER-1)];
+ float INLABUF1_float[QLOOKAHEAD];
+ float INLABUF2_float[QLOOKAHEAD];
+
+ /* High pass filter */
+ double HPstates[HPORDER];
+ float HPstates_float[HPORDER];
+
+} PreFiltBankstr;
+
+
+typedef struct {
+
+ //state vectors for each of the two analysis filters
+ double STATE_0_LOWER[2*POSTQORDER];
+ double STATE_0_UPPER[2*POSTQORDER];
+
+ /* High pass filter */
+ double HPstates1[HPORDER];
+ double HPstates2[HPORDER];
+
+ float STATE_0_LOWER_float[2*POSTQORDER];
+ float STATE_0_UPPER_float[2*POSTQORDER];
+
+ float HPstates1_float[HPORDER];
+ float HPstates2_float[HPORDER];
+
+} PostFiltBankstr;
+
+typedef struct {
+
+ //data buffer for pitch filter
+ double ubuf[PITCH_BUFFSIZE];
+
+ //low pass state vector
+ double ystate[PITCH_DAMPORDER];
+
+ //old lag and gain
+ double oldlagp[1];
+ double oldgainp[1];
+
+} PitchFiltstr;
+
+typedef struct {
+
+ //data buffer
+ double buffer[PITCH_WLPCBUFLEN];
+
+ //state vectors
+ double istate[PITCH_WLPCORDER];
+ double weostate[PITCH_WLPCORDER];
+ double whostate[PITCH_WLPCORDER];
+
+ //LPC window -> should be a global array because constant
+ double window[PITCH_WLPCWINLEN];
+
+} WeightFiltstr;
+
+typedef struct {
+
+ //for inital estimator
+ double dec_buffer[PITCH_CORR_LEN2 + PITCH_CORR_STEP2 +
+ PITCH_MAX_LAG/2 - PITCH_FRAME_LEN/2+2];
+ double decimator_state[2*ALLPASSSECTIONS+1];
+ double hp_state[2];
+
+ double whitened_buf[QLOOKAHEAD];
+
+ double inbuf[QLOOKAHEAD];
+
+ PitchFiltstr PFstr_wght;
+ PitchFiltstr PFstr;
+ WeightFiltstr Wghtstr;
+
+} PitchAnalysisStruct;
+
+
+
+/* Have instance of struct together with other iSAC structs */
+typedef struct {
+
+ /* Previous frame length (in ms) */
+ WebRtc_Word32 prev_frame_length;
+
+ /* Previous RTP timestamp from received
+ packet (in samples relative beginning) */
+ WebRtc_Word32 prev_rec_rtp_number;
+
+ /* Send timestamp for previous packet (in ms using timeGetTime()) */
+ WebRtc_UWord32 prev_rec_send_ts;
+
+ /* Arrival time for previous packet (in ms using timeGetTime()) */
+ WebRtc_UWord32 prev_rec_arr_ts;
+
+ /* rate of previous packet, derived from RTP timestamps (in bits/s) */
+ float prev_rec_rtp_rate;
+
+ /* Time sinse the last update of the BN estimate (in ms) */
+ WebRtc_UWord32 last_update_ts;
+
+ /* Time sinse the last reduction (in ms) */
+ WebRtc_UWord32 last_reduction_ts;
+
+ /* How many times the estimate was update in the beginning */
+ WebRtc_Word32 count_tot_updates_rec;
+
+ /* The estimated bottle neck rate from there to here (in bits/s) */
+ WebRtc_Word32 rec_bw;
+ float rec_bw_inv;
+ float rec_bw_avg;
+ float rec_bw_avg_Q;
+
+ /* The estimated mean absolute jitter value,
+ as seen on this side (in ms) */
+ float rec_jitter;
+ float rec_jitter_short_term;
+ float rec_jitter_short_term_abs;
+ float rec_max_delay;
+ float rec_max_delay_avg_Q;
+
+ /* (assumed) bitrate for headers (bps) */
+ float rec_header_rate;
+
+ /* The estimated bottle neck rate from here to there (in bits/s) */
+ float send_bw_avg;
+
+ /* The estimated mean absolute jitter value, as seen on
+ the other siee (in ms) */
+ float send_max_delay_avg;
+
+ // number of packets received since last update
+ int num_pkts_rec;
+
+ int num_consec_rec_pkts_over_30k;
+
+ // flag for marking that a high speed network has been
+ // detected downstream
+ int hsn_detect_rec;
+
+ int num_consec_snt_pkts_over_30k;
+
+ // flag for marking that a high speed network has
+ // been detected upstream
+ int hsn_detect_snd;
+
+ WebRtc_UWord32 start_wait_period;
+
+ int in_wait_period;
+
+ int change_to_WB;
+
+ WebRtc_UWord32 senderTimestamp;
+ WebRtc_UWord32 receiverTimestamp;
+ //enum IsacSamplingRate incomingStreamSampFreq;
+ WebRtc_UWord16 numConsecLatePkts;
+ float consecLatency;
+ WebRtc_Word16 inWaitLatePkts;
+} BwEstimatorstr;
+
+
+typedef struct {
+
+ /* boolean, flags if previous packet exceeded B.N. */
+ int PrevExceed;
+ /* ms */
+ int ExceedAgo;
+ /* packets left to send in current burst */
+ int BurstCounter;
+ /* packets */
+ int InitCounter;
+ /* ms remaining in buffer when next packet will be sent */
+ double StillBuffered;
+
+} RateModel;
+
+
+typedef struct {
+
+ unsigned int SpaceAlloced;
+ unsigned int MaxPermAlloced;
+ double Tmp0[MAXFFTSIZE];
+ double Tmp1[MAXFFTSIZE];
+ double Tmp2[MAXFFTSIZE];
+ double Tmp3[MAXFFTSIZE];
+ int Perm[MAXFFTSIZE];
+ int factor [NFACTOR];
+
+} FFTstr;
+
+
+/* The following strutc is used to store data from encoding, to make it
+ fast and easy to construct a new bitstream with a different Bandwidth
+ estimate. All values (except framelength and minBytes) is double size to
+ handle 60 ms of data.
+*/
+typedef struct {
+
+ /* Used to keep track of if it is first or second part of 60 msec packet */
+ int startIdx;
+
+ /* Frame length in samples */
+ WebRtc_Word16 framelength;
+
+ /* Pitch Gain */
+ int pitchGain_index[2];
+
+ /* Pitch Lag */
+ double meanGain[2];
+ int pitchIndex[PITCH_SUBFRAMES*2];
+
+ /* LPC */
+ int LPCmodel[2];
+ int LPCindex_s[108*2]; /* KLT_ORDER_SHAPE = 108 */
+ int LPCindex_g[12*2]; /* KLT_ORDER_GAIN = 12 */
+ double LPCcoeffs_lo[(ORDERLO+1)*SUBFRAMES*2];
+ double LPCcoeffs_hi[(ORDERHI+1)*SUBFRAMES*2];
+
+ /* Encode Spec */
+ WebRtc_Word16 fre[FRAMESAMPLES];
+ WebRtc_Word16 fim[FRAMESAMPLES];
+ WebRtc_Word16 AvgPitchGain[2];
+
+ /* Used in adaptive mode only */
+ int minBytes;
+
+} ISAC_SaveEncData_t;
+
+
+typedef struct {
+
+ int indexLPCShape[UB_LPC_ORDER * UB16_LPC_VEC_PER_FRAME];
+ double lpcGain[SUBFRAMES<<1];
+ int lpcGainIndex[SUBFRAMES<<1];
+
+ Bitstr bitStreamObj;
+
+ WebRtc_Word16 realFFT[FRAMESAMPLES_HALF];
+ WebRtc_Word16 imagFFT[FRAMESAMPLES_HALF];
+} ISACUBSaveEncDataStruct;
+
+
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ PitchAnalysisStruct pitchanalysisstr_obj;
+ FFTstr fftstr_obj;
+ ISAC_SaveEncData_t SaveEnc_obj;
+
+ int buffer_index;
+ WebRtc_Word16 current_framesamples;
+
+ float data_buffer_float[FRAMESAMPLES_30ms];
+
+ int frame_nb;
+ double bottleneck;
+ WebRtc_Word16 new_framelength;
+ double s2nr;
+
+ /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 payloadLimitBytes30;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ WebRtc_Word16 payloadLimitBytes60;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ WebRtc_Word16 maxPayloadBytes;
+ /* Maximum allowed rate in bytes per 30 msec packet */
+ WebRtc_Word16 maxRateInBytes;
+
+ /*---
+ If set to 1 iSAC will not addapt the frame-size, if used in
+ channel-adaptive mode. The initial value will be used for all rates.
+ ---*/
+ WebRtc_Word16 enforceFrameSize;
+
+ /*-----
+ This records the BWE index the encoder injected into the bit-stream.
+ It will be used in RCU. The same BWE index of main paylaod will be in
+ the redundant payload. We can not retrive it from BWE because it is
+ a recursive procedure (WebRtcIsac_GetDownlinkBwJitIndexImpl) and has to be
+ called only once per each encode.
+ -----*/
+ WebRtc_Word16 lastBWIdx;
+} ISACLBEncStruct;
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PreFiltBankstr prefiltbankstr_obj;
+ FFTstr fftstr_obj;
+ ISACUBSaveEncDataStruct SaveEnc_obj;
+
+ int buffer_index;
+ float data_buffer_float[MAX_FRAMESAMPLES +
+ LB_TOTAL_DELAY_SAMPLES];
+ double bottleneck;
+ /* Maximum allowed number of bits for a 30 msec packet */
+ //WebRtc_Word16 payloadLimitBytes30;
+ /* Maximum allowed number of bits for both 30 and 60 msec packet */
+ //WebRtc_Word16 maxPayloadBytes;
+ WebRtc_Word16 maxPayloadSizeBytes;
+
+ double lastLPCVec[UB_LPC_ORDER];
+ WebRtc_Word16 numBytesUsed;
+ WebRtc_Word16 lastJitterInfo;
+} ISACUBEncStruct;
+
+
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ PitchFiltstr pitchfiltstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACLBDecStruct;
+
+typedef struct {
+
+ Bitstr bitstr_obj;
+ MaskFiltstr maskfiltstr_obj;
+ PostFiltBankstr postfiltbankstr_obj;
+ FFTstr fftstr_obj;
+
+} ISACUBDecStruct;
+
+
+
+typedef struct {
+
+ ISACLBEncStruct ISACencLB_obj;
+ ISACLBDecStruct ISACdecLB_obj;
+} ISACLBStruct;
+
+
+typedef struct {
+
+ ISACUBEncStruct ISACencUB_obj;
+ ISACUBDecStruct ISACdecUB_obj;
+} ISACUBStruct;
+
+/*
+ This struct is used to take a snapshot of the entropy coder and LPC gains
+ right before encoding LPC gains. This allows us to go back to that state
+ if we like to limit the payload size.
+*/
+typedef struct {
+ /* 6 lower-band & 6 upper-band */
+ double loFiltGain[SUBFRAMES];
+ double hiFiltGain[SUBFRAMES];
+ /* Upper boundary of interval W */
+ WebRtc_UWord32 W_upper;
+ WebRtc_UWord32 streamval;
+ /* Index to the current position in bytestream */
+ WebRtc_UWord32 stream_index;
+ WebRtc_UWord8 stream[3];
+} transcode_obj;
+
+
+typedef struct {
+ // lower-band codec instance
+ ISACLBStruct instLB;
+ // upper-band codec instance
+ ISACUBStruct instUB;
+
+ // Bandwidth Estimator and model for the rate.
+ BwEstimatorstr bwestimator_obj;
+ RateModel rate_data_obj;
+ double MaxDelay;
+
+ /* 0 = adaptive; 1 = instantaneous */
+ WebRtc_Word16 codingMode;
+
+ // overall bottleneck of the codec
+ WebRtc_Word32 bottleneck;
+
+ // QMF Filter state
+ WebRtc_Word32 analysisFBState1[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 analysisFBState2[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 synthesisFBState1[FB_STATE_SIZE_WORD32];
+ WebRtc_Word32 synthesisFBState2[FB_STATE_SIZE_WORD32];
+
+ // Error Code
+ WebRtc_Word16 errorCode;
+
+ // bandwidth of the encoded audio 8, 12 or 16 kHz
+ enum ISACBandwidth bandwidthKHz;
+ // Sampling rate of audio, encoder and decode, 8 or 16 kHz
+ enum IsacSamplingRate encoderSamplingRateKHz;
+ enum IsacSamplingRate decoderSamplingRateKHz;
+ // Flag to keep track of initializations, lower & upper-band
+ // encoder and decoder.
+ WebRtc_Word16 initFlag;
+
+ // Flag to to indicate signal bandwidth switch
+ WebRtc_Word16 resetFlag_8kHz;
+
+ // Maximum allowed rate, measured in Bytes per 30 ms.
+ WebRtc_Word16 maxRateBytesPer30Ms;
+ // Maximum allowed payload-size, measured in Bytes.
+ WebRtc_Word16 maxPayloadSizeBytes;
+} ISACMainStruct;
+
+#endif /* WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_STRUCTS_H_ */
diff --git a/src/mod/codecs/mod_isac/transform.c b/src/mod/codecs/mod_isac/transform.c
new file mode 100644
index 0000000000..97b801ac49
--- /dev/null
+++ b/src/mod/codecs/mod_isac/transform.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "settings.h"
+#include "fft.h"
+#include "codec.h"
+#include "os_specific_inline.h"
+#include
+
+static double costab1[FRAMESAMPLES_HALF];
+static double sintab1[FRAMESAMPLES_HALF];
+static double costab2[FRAMESAMPLES_QUARTER];
+static double sintab2[FRAMESAMPLES_QUARTER];
+
+void WebRtcIsac_InitTransform()
+{
+ int k;
+ double fact, phase;
+
+ fact = PI / (FRAMESAMPLES_HALF);
+ phase = 0.0;
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ costab1[k] = cos(phase);
+ sintab1[k] = sin(phase);
+ phase += fact;
+ }
+
+ fact = PI * ((double) (FRAMESAMPLES_HALF - 1)) / ((double) FRAMESAMPLES_HALF);
+ phase = 0.5 * fact;
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ costab2[k] = cos(phase);
+ sintab2[k] = sin(phase);
+ phase += fact;
+ }
+}
+
+
+void WebRtcIsac_Time2Spec(double *inre1,
+ double *inre2,
+ WebRtc_Word16 *outreQ7,
+ WebRtc_Word16 *outimQ7,
+ FFTstr *fftstr_obj)
+{
+
+ int k;
+ int dims[1];
+ double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+ double tmpre[FRAMESAMPLES_HALF], tmpim[FRAMESAMPLES_HALF];
+
+
+ dims[0] = FRAMESAMPLES_HALF;
+
+
+ /* Multiply with complex exponentials and combine into one complex vector */
+ fact = 0.5 / sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tmp1r = costab1[k];
+ tmp1i = sintab1[k];
+ tmpre[k] = (inre1[k] * tmp1r + inre2[k] * tmp1i) * fact;
+ tmpim[k] = (inre2[k] * tmp1r - inre1[k] * tmp1i) * fact;
+ }
+
+
+ /* Get DFT */
+ WebRtcIsac_Fftns(1, dims, tmpre, tmpim, -1, 1.0, fftstr_obj);
+
+ /* Use symmetry to separate into two complex vectors and center frames in time around zero */
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ xr = tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ yi = -tmpre[k] + tmpre[FRAMESAMPLES_HALF - 1 - k];
+ xi = tmpim[k] - tmpim[FRAMESAMPLES_HALF - 1 - k];
+ yr = tmpim[k] + tmpim[FRAMESAMPLES_HALF - 1 - k];
+
+ tmp1r = costab2[k];
+ tmp1i = sintab2[k];
+ outreQ7[k] = (WebRtc_Word16)WebRtcIsac_lrint((xr * tmp1r - xi * tmp1i) * 128.0);
+ outimQ7[k] = (WebRtc_Word16)WebRtcIsac_lrint((xr * tmp1i + xi * tmp1r) * 128.0);
+ outreQ7[FRAMESAMPLES_HALF - 1 - k] = (WebRtc_Word16)WebRtcIsac_lrint((-yr * tmp1i - yi * tmp1r) * 128.0);
+ outimQ7[FRAMESAMPLES_HALF - 1 - k] = (WebRtc_Word16)WebRtcIsac_lrint((-yr * tmp1r + yi * tmp1i) * 128.0);
+ }
+}
+
+
+void WebRtcIsac_Spec2time(double *inre, double *inim, double *outre1, double *outre2, FFTstr *fftstr_obj)
+{
+
+ int k;
+ double tmp1r, tmp1i, xr, xi, yr, yi, fact;
+
+ int dims;
+
+ dims = FRAMESAMPLES_HALF;
+
+ for (k = 0; k < FRAMESAMPLES_QUARTER; k++) {
+ /* Move zero in time to beginning of frames */
+ tmp1r = costab2[k];
+ tmp1i = sintab2[k];
+ xr = inre[k] * tmp1r + inim[k] * tmp1i;
+ xi = inim[k] * tmp1r - inre[k] * tmp1i;
+ yr = -inim[FRAMESAMPLES_HALF - 1 - k] * tmp1r - inre[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+ yi = -inre[FRAMESAMPLES_HALF - 1 - k] * tmp1r + inim[FRAMESAMPLES_HALF - 1 - k] * tmp1i;
+
+ /* Combine into one vector, z = x + j * y */
+ outre1[k] = xr - yi;
+ outre1[FRAMESAMPLES_HALF - 1 - k] = xr + yi;
+ outre2[k] = xi + yr;
+ outre2[FRAMESAMPLES_HALF - 1 - k] = -xi + yr;
+ }
+
+
+ /* Get IDFT */
+ WebRtcIsac_Fftns(1, &dims, outre1, outre2, 1, FRAMESAMPLES_HALF, fftstr_obj);
+
+
+ /* Demodulate and separate */
+ fact = sqrt(FRAMESAMPLES_HALF);
+ for (k = 0; k < FRAMESAMPLES_HALF; k++) {
+ tmp1r = costab1[k];
+ tmp1i = sintab1[k];
+ xr = (outre1[k] * tmp1r - outre2[k] * tmp1i) * fact;
+ outre2[k] = (outre2[k] * tmp1r + outre1[k] * tmp1i) * fact;
+ outre1[k] = xr;
+ }
+}
diff --git a/src/mod/codecs/mod_isac/typedefs.h b/src/mod/codecs/mod_isac/typedefs.h
new file mode 100644
index 0000000000..ba87309638
--- /dev/null
+++ b/src/mod/codecs/mod_isac/typedefs.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file contains platform-specific typedefs and defines.
+
+#ifndef WEBRTC_TYPEDEFS_H_
+#define WEBRTC_TYPEDEFS_H_
+
+// Reserved words definitions
+// TODO(andrew): Look at removing these.
+#define WEBRTC_EXTERN extern
+#define G_CONST const
+#define WEBRTC_INLINE extern __inline
+
+// Define WebRTC preprocessor identifiers based on the current build platform.
+// TODO(andrew): Clean these up. We can probably remove everything in this
+// block.
+// - TARGET_MAC_INTEL and TARGET_MAC aren't used anywhere.
+// - In the few places where TARGET_PC is used, it should be replaced by
+// something more specific.
+// - Do we really support PowerPC? Probably not. Remove WEBRTC_MAC_INTEL
+// from build/common.gypi as well.
+#if defined(WIN32)
+ // Windows & Windows Mobile.
+ #if !defined(WEBRTC_TARGET_PC)
+ #define WEBRTC_TARGET_PC
+ #endif
+#elif defined(__APPLE__)
+ // Mac OS X.
+ #if defined(__LITTLE_ENDIAN__ )
+ #if !defined(WEBRTC_TARGET_MAC_INTEL)
+ #define WEBRTC_TARGET_MAC_INTEL
+ #endif
+ #else
+ #if !defined(WEBRTC_TARGET_MAC)
+ #define WEBRTC_TARGET_MAC
+ #endif
+ #endif
+#else
+ // Linux etc.
+ #if !defined(WEBRTC_TARGET_PC)
+ #define WEBRTC_TARGET_PC
+ #endif
+#endif
+
+// Derived from Chromium's build/build_config.h
+// Processor architecture detection. For more info on what's defined, see:
+// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
+// http://www.agner.org/optimize/calling_conventions.pdf
+// or with gcc, run: "echo | gcc -E -dM -"
+// TODO(andrew): replace WEBRTC_LITTLE_ENDIAN with WEBRTC_ARCH_LITTLE_ENDIAN?
+#if defined(_M_X64) || defined(__x86_64__)
+#define WEBRTC_ARCH_X86_FAMILY
+#define WEBRTC_ARCH_X86_64
+#define WEBRTC_ARCH_64_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(_M_IX86) || defined(__i386__)
+#define WEBRTC_ARCH_X86_FAMILY
+#define WEBRTC_ARCH_X86
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__ARMEL__)
+// TODO(andrew): We'd prefer to control platform defines here, but this is
+// currently provided by the Android makefiles. Commented to avoid duplicate
+// definition warnings.
+//#define WEBRTC_ARCH_ARM
+// TODO(andrew): Chromium uses the following two defines. Should we switch?
+//#define WEBRTC_ARCH_ARM_FAMILY
+//#define WEBRTC_ARCH_ARMEL
+#define WEBRTC_ARCH_32_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#else
+#error Please add support for your architecture in typedefs.h
+#endif
+
+#if defined(__SSE2__) || defined(_MSC_VER)
+#define WEBRTC_USE_SSE2
+#endif
+
+#if defined(WEBRTC_TARGET_PC)
+
+#if !defined(_MSC_VER)
+ #include
+#else
+ // Define C99 equivalent types.
+ // Since MSVC doesn't include these headers, we have to write our own
+ // version to provide a compatibility layer between MSVC and the WebRTC
+ // headers.
+ typedef signed char int8_t;
+ typedef signed short int16_t;
+ typedef signed int int32_t;
+ typedef signed long long int64_t;
+ typedef unsigned char uint8_t;
+ typedef unsigned short uint16_t;
+ typedef unsigned int uint32_t;
+ typedef unsigned long long uint64_t;
+#endif
+
+#if defined(WIN32)
+ typedef __int64 WebRtc_Word64;
+ typedef unsigned __int64 WebRtc_UWord64;
+#else
+ typedef int64_t WebRtc_Word64;
+ typedef uint64_t WebRtc_UWord64;
+#endif
+ typedef int32_t WebRtc_Word32;
+ typedef uint32_t WebRtc_UWord32;
+ typedef int16_t WebRtc_Word16;
+ typedef uint16_t WebRtc_UWord16;
+ typedef char WebRtc_Word8;
+ typedef uint8_t WebRtc_UWord8;
+
+ // Define endian for the platform
+ #define WEBRTC_LITTLE_ENDIAN
+
+#elif defined(WEBRTC_TARGET_MAC_INTEL)
+ #include
+
+ typedef int64_t WebRtc_Word64;
+ typedef uint64_t WebRtc_UWord64;
+ typedef int32_t WebRtc_Word32;
+ typedef uint32_t WebRtc_UWord32;
+ typedef int16_t WebRtc_Word16;
+ typedef char WebRtc_Word8;
+ typedef uint16_t WebRtc_UWord16;
+ typedef uint8_t WebRtc_UWord8;
+
+ // Define endian for the platform
+ #define WEBRTC_LITTLE_ENDIAN
+
+#else
+ #error "No platform defined for WebRTC type definitions (typedefs.h)"
+#endif
+
+#endif // WEBRTC_TYPEDEFS_H_
diff --git a/src/mod/codecs/mod_isac/vector_scaling_operations.c b/src/mod/codecs/mod_isac/vector_scaling_operations.c
new file mode 100644
index 0000000000..20d239cabe
--- /dev/null
+++ b/src/mod/codecs/mod_isac/vector_scaling_operations.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains implementations of the functions
+ * WebRtcSpl_VectorBitShiftW16()
+ * WebRtcSpl_VectorBitShiftW32()
+ * WebRtcSpl_VectorBitShiftW32ToW16()
+ * WebRtcSpl_ScaleVector()
+ * WebRtcSpl_ScaleVectorWithSat()
+ * WebRtcSpl_ScaleAndAddVectors()
+ *
+ * The description header can be found in signal_processing_library.h
+ *
+ */
+
+#include "signal_processing_library.h"
+
+void WebRtcSpl_VectorBitShiftW16(WebRtc_Word16 *res,
+ WebRtc_Word16 length,
+ G_CONST WebRtc_Word16 *in,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts > 0)
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = ((*in++) >> right_shifts);
+ }
+ } else
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = ((*in++) << (-right_shifts));
+ }
+ }
+}
+
+void WebRtcSpl_VectorBitShiftW32(WebRtc_Word32 *out_vector,
+ WebRtc_Word16 vector_length,
+ G_CONST WebRtc_Word32 *in_vector,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts > 0)
+ {
+ for (i = vector_length; i > 0; i--)
+ {
+ (*out_vector++) = ((*in_vector++) >> right_shifts);
+ }
+ } else
+ {
+ for (i = vector_length; i > 0; i--)
+ {
+ (*out_vector++) = ((*in_vector++) << (-right_shifts));
+ }
+ }
+}
+
+void WebRtcSpl_VectorBitShiftW32ToW16(WebRtc_Word16 *res,
+ WebRtc_Word16 length,
+ G_CONST WebRtc_Word32 *in,
+ WebRtc_Word16 right_shifts)
+{
+ int i;
+
+ if (right_shifts >= 0)
+ {
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = (WebRtc_Word16)((*in++) >> right_shifts);
+ }
+ } else
+ {
+ WebRtc_Word16 left_shifts = -right_shifts;
+ for (i = length; i > 0; i--)
+ {
+ (*res++) = (WebRtc_Word16)((*in++) << left_shifts);
+ }
+ }
+}
+
+void WebRtcSpl_ScaleVector(G_CONST WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector,
+ WebRtc_Word16 gain, WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts
+ int i;
+ G_CONST WebRtc_Word16 *inptr;
+ WebRtc_Word16 *outptr;
+
+ inptr = in_vector;
+ outptr = out_vector;
+
+ for (i = 0; i < in_vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts);
+ }
+}
+
+void WebRtcSpl_ScaleVectorWithSat(G_CONST WebRtc_Word16 *in_vector, WebRtc_Word16 *out_vector,
+ WebRtc_Word16 gain, WebRtc_Word16 in_vector_length,
+ WebRtc_Word16 right_shifts)
+{
+ // Performs vector operation: out_vector = (gain*in_vector)>>right_shifts
+ int i;
+ WebRtc_Word32 tmpW32;
+ G_CONST WebRtc_Word16 *inptr;
+ WebRtc_Word16 *outptr;
+
+ inptr = in_vector;
+ outptr = out_vector;
+
+ for (i = 0; i < in_vector_length; i++)
+ {
+ tmpW32 = WEBRTC_SPL_MUL_16_16_RSFT(*inptr++, gain, right_shifts);
+ (*outptr++) = WebRtcSpl_SatW32ToW16(tmpW32);
+ }
+}
+
+void WebRtcSpl_ScaleAndAddVectors(G_CONST WebRtc_Word16 *in1, WebRtc_Word16 gain1, int shift1,
+ G_CONST WebRtc_Word16 *in2, WebRtc_Word16 gain2, int shift2,
+ WebRtc_Word16 *out, int vector_length)
+{
+ // Performs vector operation: out = (gain1*in1)>>shift1 + (gain2*in2)>>shift2
+ int i;
+ G_CONST WebRtc_Word16 *in1ptr;
+ G_CONST WebRtc_Word16 *in2ptr;
+ WebRtc_Word16 *outptr;
+
+ in1ptr = in1;
+ in2ptr = in2;
+ outptr = out;
+
+ for (i = 0; i < vector_length; i++)
+ {
+ (*outptr++) = (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gain1, *in1ptr++, shift1)
+ + (WebRtc_Word16)WEBRTC_SPL_MUL_16_16_RSFT(gain2, *in2ptr++, shift2);
+ }
+}
diff --git a/src/mod/codecs/mod_isac/webrtc_fft_t_1024_8.c b/src/mod/codecs/mod_isac/webrtc_fft_t_1024_8.c
new file mode 100644
index 0000000000..b587380523
--- /dev/null
+++ b/src/mod/codecs/mod_isac/webrtc_fft_t_1024_8.c
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the Q14 radix-8 tables used in ARM9e optimizations.
+ *
+ */
+
+extern const int s_Q14S_8;
+const int s_Q14S_8 = 1024;
+extern const unsigned short t_Q14S_8[2032];
+const unsigned short t_Q14S_8[2032] = {
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x396b,0x0646 ,0x3cc8,0x0324 ,0x35eb,0x0964 ,
+ 0x3249,0x0c7c ,0x396b,0x0646 ,0x2aaa,0x1294 ,
+ 0x2aaa,0x1294 ,0x35eb,0x0964 ,0x1e7e,0x1b5d ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x1a46,0x1e2b ,0x2e88,0x0f8d ,0x0471,0x2afb ,
+ 0x11a8,0x238e ,0x2aaa,0x1294 ,0xf721,0x3179 ,
+ 0x08df,0x289a ,0x26b3,0x1590 ,0xea02,0x36e5 ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xf721,0x3179 ,0x1e7e,0x1b5d ,0xd178,0x3e15 ,
+ 0xee58,0x3537 ,0x1a46,0x1e2b ,0xc695,0x3fb1 ,
+ 0xe5ba,0x3871 ,0x15fe,0x20e7 ,0xbcf0,0x3fec ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xd556,0x3d3f ,0x0d48,0x2620 ,0xae2e,0x3c42 ,
+ 0xcdb7,0x3ec5 ,0x08df,0x289a ,0xa963,0x3871 ,
+ 0xc695,0x3fb1 ,0x0471,0x2afb ,0xa678,0x3368 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xba09,0x3fb1 ,0xfb8f,0x2f6c ,0xa678,0x2620 ,
+ 0xb4be,0x3ec5 ,0xf721,0x3179 ,0xa963,0x1e2b ,
+ 0xb02d,0x3d3f ,0xf2b8,0x3368 ,0xae2e,0x1590 ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xa963,0x3871 ,0xea02,0x36e5 ,0xbcf0,0x0324 ,
+ 0xa73b,0x3537 ,0xe5ba,0x3871 ,0xc695,0xf9ba ,
+ 0xa5ed,0x3179 ,0xe182,0x39db ,0xd178,0xf073 ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xa5ed,0x289a ,0xd94d,0x3c42 ,0xea02,0xdf19 ,
+ 0xa73b,0x238e ,0xd556,0x3d3f ,0xf721,0xd766 ,
+ 0xa963,0x1e2b ,0xd178,0x3e15 ,0x0471,0xd094 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0xb02d,0x1294 ,0xca15,0x3f4f ,0x1e7e,0xc625 ,
+ 0xb4be,0x0c7c ,0xc695,0x3fb1 ,0x2aaa,0xc2c1 ,
+ 0xba09,0x0646 ,0xc338,0x3fec ,0x35eb,0xc0b1 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3e69,0x0192 ,0x3f36,0x00c9 ,0x3d9a,0x025b ,
+ 0x3cc8,0x0324 ,0x3e69,0x0192 ,0x3b1e,0x04b5 ,
+ 0x3b1e,0x04b5 ,0x3d9a,0x025b ,0x388e,0x070e ,
+ 0x396b,0x0646 ,0x3cc8,0x0324 ,0x35eb,0x0964 ,
+ 0x37af,0x07d6 ,0x3bf4,0x03ed ,0x3334,0x0bb7 ,
+ 0x35eb,0x0964 ,0x3b1e,0x04b5 ,0x306c,0x0e06 ,
+ 0x341e,0x0af1 ,0x3a46,0x057e ,0x2d93,0x1050 ,
+ 0x3249,0x0c7c ,0x396b,0x0646 ,0x2aaa,0x1294 ,
+ 0x306c,0x0e06 ,0x388e,0x070e ,0x27b3,0x14d2 ,
+ 0x2e88,0x0f8d ,0x37af,0x07d6 ,0x24ae,0x1709 ,
+ 0x2c9d,0x1112 ,0x36ce,0x089d ,0x219c,0x1937 ,
+ 0x2aaa,0x1294 ,0x35eb,0x0964 ,0x1e7e,0x1b5d ,
+ 0x28b2,0x1413 ,0x3505,0x0a2b ,0x1b56,0x1d79 ,
+ 0x26b3,0x1590 ,0x341e,0x0af1 ,0x1824,0x1f8c ,
+ 0x24ae,0x1709 ,0x3334,0x0bb7 ,0x14ea,0x2193 ,
+ 0x22a3,0x187e ,0x3249,0x0c7c ,0x11a8,0x238e ,
+ 0x2093,0x19ef ,0x315b,0x0d41 ,0x0e61,0x257e ,
+ 0x1e7e,0x1b5d ,0x306c,0x0e06 ,0x0b14,0x2760 ,
+ 0x1c64,0x1cc6 ,0x2f7b,0x0eca ,0x07c4,0x2935 ,
+ 0x1a46,0x1e2b ,0x2e88,0x0f8d ,0x0471,0x2afb ,
+ 0x1824,0x1f8c ,0x2d93,0x1050 ,0x011c,0x2cb2 ,
+ 0x15fe,0x20e7 ,0x2c9d,0x1112 ,0xfdc7,0x2e5a ,
+ 0x13d5,0x223d ,0x2ba4,0x11d3 ,0xfa73,0x2ff2 ,
+ 0x11a8,0x238e ,0x2aaa,0x1294 ,0xf721,0x3179 ,
+ 0x0f79,0x24da ,0x29af,0x1354 ,0xf3d2,0x32ef ,
+ 0x0d48,0x2620 ,0x28b2,0x1413 ,0xf087,0x3453 ,
+ 0x0b14,0x2760 ,0x27b3,0x14d2 ,0xed41,0x35a5 ,
+ 0x08df,0x289a ,0x26b3,0x1590 ,0xea02,0x36e5 ,
+ 0x06a9,0x29ce ,0x25b1,0x164c ,0xe6cb,0x3812 ,
+ 0x0471,0x2afb ,0x24ae,0x1709 ,0xe39c,0x392b ,
+ 0x0239,0x2c21 ,0x23a9,0x17c4 ,0xe077,0x3a30 ,
+ 0x0000,0x2d41 ,0x22a3,0x187e ,0xdd5d,0x3b21 ,
+ 0xfdc7,0x2e5a ,0x219c,0x1937 ,0xda4f,0x3bfd ,
+ 0xfb8f,0x2f6c ,0x2093,0x19ef ,0xd74e,0x3cc5 ,
+ 0xf957,0x3076 ,0x1f89,0x1aa7 ,0xd45c,0x3d78 ,
+ 0xf721,0x3179 ,0x1e7e,0x1b5d ,0xd178,0x3e15 ,
+ 0xf4ec,0x3274 ,0x1d72,0x1c12 ,0xcea5,0x3e9d ,
+ 0xf2b8,0x3368 ,0x1c64,0x1cc6 ,0xcbe2,0x3f0f ,
+ 0xf087,0x3453 ,0x1b56,0x1d79 ,0xc932,0x3f6b ,
+ 0xee58,0x3537 ,0x1a46,0x1e2b ,0xc695,0x3fb1 ,
+ 0xec2b,0x3612 ,0x1935,0x1edc ,0xc40c,0x3fe1 ,
+ 0xea02,0x36e5 ,0x1824,0x1f8c ,0xc197,0x3ffb ,
+ 0xe7dc,0x37b0 ,0x1711,0x203a ,0xbf38,0x3fff ,
+ 0xe5ba,0x3871 ,0x15fe,0x20e7 ,0xbcf0,0x3fec ,
+ 0xe39c,0x392b ,0x14ea,0x2193 ,0xbabf,0x3fc4 ,
+ 0xe182,0x39db ,0x13d5,0x223d ,0xb8a6,0x3f85 ,
+ 0xdf6d,0x3a82 ,0x12bf,0x22e7 ,0xb6a5,0x3f30 ,
+ 0xdd5d,0x3b21 ,0x11a8,0x238e ,0xb4be,0x3ec5 ,
+ 0xdb52,0x3bb6 ,0x1091,0x2435 ,0xb2f2,0x3e45 ,
+ 0xd94d,0x3c42 ,0x0f79,0x24da ,0xb140,0x3daf ,
+ 0xd74e,0x3cc5 ,0x0e61,0x257e ,0xafa9,0x3d03 ,
+ 0xd556,0x3d3f ,0x0d48,0x2620 ,0xae2e,0x3c42 ,
+ 0xd363,0x3daf ,0x0c2e,0x26c1 ,0xacd0,0x3b6d ,
+ 0xd178,0x3e15 ,0x0b14,0x2760 ,0xab8e,0x3a82 ,
+ 0xcf94,0x3e72 ,0x09fa,0x27fe ,0xaa6a,0x3984 ,
+ 0xcdb7,0x3ec5 ,0x08df,0x289a ,0xa963,0x3871 ,
+ 0xcbe2,0x3f0f ,0x07c4,0x2935 ,0xa87b,0x374b ,
+ 0xca15,0x3f4f ,0x06a9,0x29ce ,0xa7b1,0x3612 ,
+ 0xc851,0x3f85 ,0x058d,0x2a65 ,0xa705,0x34c6 ,
+ 0xc695,0x3fb1 ,0x0471,0x2afb ,0xa678,0x3368 ,
+ 0xc4e2,0x3fd4 ,0x0355,0x2b8f ,0xa60b,0x31f8 ,
+ 0xc338,0x3fec ,0x0239,0x2c21 ,0xa5bc,0x3076 ,
+ 0xc197,0x3ffb ,0x011c,0x2cb2 ,0xa58d,0x2ee4 ,
+ 0xc000,0x4000 ,0x0000,0x2d41 ,0xa57e,0x2d41 ,
+ 0xbe73,0x3ffb ,0xfee4,0x2dcf ,0xa58d,0x2b8f ,
+ 0xbcf0,0x3fec ,0xfdc7,0x2e5a ,0xa5bc,0x29ce ,
+ 0xbb77,0x3fd4 ,0xfcab,0x2ee4 ,0xa60b,0x27fe ,
+ 0xba09,0x3fb1 ,0xfb8f,0x2f6c ,0xa678,0x2620 ,
+ 0xb8a6,0x3f85 ,0xfa73,0x2ff2 ,0xa705,0x2435 ,
+ 0xb74d,0x3f4f ,0xf957,0x3076 ,0xa7b1,0x223d ,
+ 0xb600,0x3f0f ,0xf83c,0x30f9 ,0xa87b,0x203a ,
+ 0xb4be,0x3ec5 ,0xf721,0x3179 ,0xa963,0x1e2b ,
+ 0xb388,0x3e72 ,0xf606,0x31f8 ,0xaa6a,0x1c12 ,
+ 0xb25e,0x3e15 ,0xf4ec,0x3274 ,0xab8e,0x19ef ,
+ 0xb140,0x3daf ,0xf3d2,0x32ef ,0xacd0,0x17c4 ,
+ 0xb02d,0x3d3f ,0xf2b8,0x3368 ,0xae2e,0x1590 ,
+ 0xaf28,0x3cc5 ,0xf19f,0x33df ,0xafa9,0x1354 ,
+ 0xae2e,0x3c42 ,0xf087,0x3453 ,0xb140,0x1112 ,
+ 0xad41,0x3bb6 ,0xef6f,0x34c6 ,0xb2f2,0x0eca ,
+ 0xac61,0x3b21 ,0xee58,0x3537 ,0xb4be,0x0c7c ,
+ 0xab8e,0x3a82 ,0xed41,0x35a5 ,0xb6a5,0x0a2b ,
+ 0xaac8,0x39db ,0xec2b,0x3612 ,0xb8a6,0x07d6 ,
+ 0xaa0f,0x392b ,0xeb16,0x367d ,0xbabf,0x057e ,
+ 0xa963,0x3871 ,0xea02,0x36e5 ,0xbcf0,0x0324 ,
+ 0xa8c5,0x37b0 ,0xe8ef,0x374b ,0xbf38,0x00c9 ,
+ 0xa834,0x36e5 ,0xe7dc,0x37b0 ,0xc197,0xfe6e ,
+ 0xa7b1,0x3612 ,0xe6cb,0x3812 ,0xc40c,0xfc13 ,
+ 0xa73b,0x3537 ,0xe5ba,0x3871 ,0xc695,0xf9ba ,
+ 0xa6d3,0x3453 ,0xe4aa,0x38cf ,0xc932,0xf763 ,
+ 0xa678,0x3368 ,0xe39c,0x392b ,0xcbe2,0xf50f ,
+ 0xa62c,0x3274 ,0xe28e,0x3984 ,0xcea5,0xf2bf ,
+ 0xa5ed,0x3179 ,0xe182,0x39db ,0xd178,0xf073 ,
+ 0xa5bc,0x3076 ,0xe077,0x3a30 ,0xd45c,0xee2d ,
+ 0xa599,0x2f6c ,0xdf6d,0x3a82 ,0xd74e,0xebed ,
+ 0xa585,0x2e5a ,0xde64,0x3ad3 ,0xda4f,0xe9b4 ,
+ 0xa57e,0x2d41 ,0xdd5d,0x3b21 ,0xdd5d,0xe782 ,
+ 0xa585,0x2c21 ,0xdc57,0x3b6d ,0xe077,0xe559 ,
+ 0xa599,0x2afb ,0xdb52,0x3bb6 ,0xe39c,0xe33a ,
+ 0xa5bc,0x29ce ,0xda4f,0x3bfd ,0xe6cb,0xe124 ,
+ 0xa5ed,0x289a ,0xd94d,0x3c42 ,0xea02,0xdf19 ,
+ 0xa62c,0x2760 ,0xd84d,0x3c85 ,0xed41,0xdd19 ,
+ 0xa678,0x2620 ,0xd74e,0x3cc5 ,0xf087,0xdb26 ,
+ 0xa6d3,0x24da ,0xd651,0x3d03 ,0xf3d2,0xd93f ,
+ 0xa73b,0x238e ,0xd556,0x3d3f ,0xf721,0xd766 ,
+ 0xa7b1,0x223d ,0xd45c,0x3d78 ,0xfa73,0xd59b ,
+ 0xa834,0x20e7 ,0xd363,0x3daf ,0xfdc7,0xd3df ,
+ 0xa8c5,0x1f8c ,0xd26d,0x3de3 ,0x011c,0xd231 ,
+ 0xa963,0x1e2b ,0xd178,0x3e15 ,0x0471,0xd094 ,
+ 0xaa0f,0x1cc6 ,0xd085,0x3e45 ,0x07c4,0xcf07 ,
+ 0xaac8,0x1b5d ,0xcf94,0x3e72 ,0x0b14,0xcd8c ,
+ 0xab8e,0x19ef ,0xcea5,0x3e9d ,0x0e61,0xcc21 ,
+ 0xac61,0x187e ,0xcdb7,0x3ec5 ,0x11a8,0xcac9 ,
+ 0xad41,0x1709 ,0xcccc,0x3eeb ,0x14ea,0xc983 ,
+ 0xae2e,0x1590 ,0xcbe2,0x3f0f ,0x1824,0xc850 ,
+ 0xaf28,0x1413 ,0xcafb,0x3f30 ,0x1b56,0xc731 ,
+ 0xb02d,0x1294 ,0xca15,0x3f4f ,0x1e7e,0xc625 ,
+ 0xb140,0x1112 ,0xc932,0x3f6b ,0x219c,0xc52d ,
+ 0xb25e,0x0f8d ,0xc851,0x3f85 ,0x24ae,0xc44a ,
+ 0xb388,0x0e06 ,0xc772,0x3f9c ,0x27b3,0xc37b ,
+ 0xb4be,0x0c7c ,0xc695,0x3fb1 ,0x2aaa,0xc2c1 ,
+ 0xb600,0x0af1 ,0xc5ba,0x3fc4 ,0x2d93,0xc21d ,
+ 0xb74d,0x0964 ,0xc4e2,0x3fd4 ,0x306c,0xc18e ,
+ 0xb8a6,0x07d6 ,0xc40c,0x3fe1 ,0x3334,0xc115 ,
+ 0xba09,0x0646 ,0xc338,0x3fec ,0x35eb,0xc0b1 ,
+ 0xbb77,0x04b5 ,0xc266,0x3ff5 ,0x388e,0xc064 ,
+ 0xbcf0,0x0324 ,0xc197,0x3ffb ,0x3b1e,0xc02c ,
+ 0xbe73,0x0192 ,0xc0ca,0x3fff ,0x3d9a,0xc00b ,
+ 0x4000,0x0000 ,0x3f9b,0x0065 ,0x3f36,0x00c9 ,
+ 0x3ed0,0x012e ,0x3e69,0x0192 ,0x3e02,0x01f7 ,
+ 0x3d9a,0x025b ,0x3d31,0x02c0 ,0x3cc8,0x0324 ,
+ 0x3c5f,0x0388 ,0x3bf4,0x03ed ,0x3b8a,0x0451 ,
+ 0x3b1e,0x04b5 ,0x3ab2,0x051a ,0x3a46,0x057e ,
+ 0x39d9,0x05e2 ,0x396b,0x0646 ,0x38fd,0x06aa ,
+ 0x388e,0x070e ,0x381f,0x0772 ,0x37af,0x07d6 ,
+ 0x373f,0x0839 ,0x36ce,0x089d ,0x365d,0x0901 ,
+ 0x35eb,0x0964 ,0x3578,0x09c7 ,0x3505,0x0a2b ,
+ 0x3492,0x0a8e ,0x341e,0x0af1 ,0x33a9,0x0b54 ,
+ 0x3334,0x0bb7 ,0x32bf,0x0c1a ,0x3249,0x0c7c ,
+ 0x31d2,0x0cdf ,0x315b,0x0d41 ,0x30e4,0x0da4 ,
+ 0x306c,0x0e06 ,0x2ff4,0x0e68 ,0x2f7b,0x0eca ,
+ 0x2f02,0x0f2b ,0x2e88,0x0f8d ,0x2e0e,0x0fee ,
+ 0x2d93,0x1050 ,0x2d18,0x10b1 ,0x2c9d,0x1112 ,
+ 0x2c21,0x1173 ,0x2ba4,0x11d3 ,0x2b28,0x1234 ,
+ 0x2aaa,0x1294 ,0x2a2d,0x12f4 ,0x29af,0x1354 ,
+ 0x2931,0x13b4 ,0x28b2,0x1413 ,0x2833,0x1473 ,
+ 0x27b3,0x14d2 ,0x2733,0x1531 ,0x26b3,0x1590 ,
+ 0x2632,0x15ee ,0x25b1,0x164c ,0x252f,0x16ab ,
+ 0x24ae,0x1709 ,0x242b,0x1766 ,0x23a9,0x17c4 ,
+ 0x2326,0x1821 ,0x22a3,0x187e ,0x221f,0x18db ,
+ 0x219c,0x1937 ,0x2117,0x1993 ,0x2093,0x19ef ,
+ 0x200e,0x1a4b ,0x1f89,0x1aa7 ,0x1f04,0x1b02 ,
+ 0x1e7e,0x1b5d ,0x1df8,0x1bb8 ,0x1d72,0x1c12 ,
+ 0x1ceb,0x1c6c ,0x1c64,0x1cc6 ,0x1bdd,0x1d20 ,
+ 0x1b56,0x1d79 ,0x1ace,0x1dd3 ,0x1a46,0x1e2b ,
+ 0x19be,0x1e84 ,0x1935,0x1edc ,0x18ad,0x1f34 ,
+ 0x1824,0x1f8c ,0x179b,0x1fe3 ,0x1711,0x203a ,
+ 0x1688,0x2091 ,0x15fe,0x20e7 ,0x1574,0x213d ,
+ 0x14ea,0x2193 ,0x145f,0x21e8 ,0x13d5,0x223d ,
+ 0x134a,0x2292 ,0x12bf,0x22e7 ,0x1234,0x233b ,
+ 0x11a8,0x238e ,0x111d,0x23e2 ,0x1091,0x2435 ,
+ 0x1005,0x2488 ,0x0f79,0x24da ,0x0eed,0x252c ,
+ 0x0e61,0x257e ,0x0dd4,0x25cf ,0x0d48,0x2620 ,
+ 0x0cbb,0x2671 ,0x0c2e,0x26c1 ,0x0ba1,0x2711 ,
+ 0x0b14,0x2760 ,0x0a87,0x27af ,0x09fa,0x27fe ,
+ 0x096d,0x284c ,0x08df,0x289a ,0x0852,0x28e7 ,
+ 0x07c4,0x2935 ,0x0736,0x2981 ,0x06a9,0x29ce ,
+ 0x061b,0x2a1a ,0x058d,0x2a65 ,0x04ff,0x2ab0 ,
+ 0x0471,0x2afb ,0x03e3,0x2b45 ,0x0355,0x2b8f ,
+ 0x02c7,0x2bd8 ,0x0239,0x2c21 ,0x01aa,0x2c6a ,
+ 0x011c,0x2cb2 ,0x008e,0x2cfa ,0x0000,0x2d41 ,
+ 0xff72,0x2d88 ,0xfee4,0x2dcf ,0xfe56,0x2e15 ,
+ 0xfdc7,0x2e5a ,0xfd39,0x2e9f ,0xfcab,0x2ee4 ,
+ 0xfc1d,0x2f28 ,0xfb8f,0x2f6c ,0xfb01,0x2faf ,
+ 0xfa73,0x2ff2 ,0xf9e5,0x3034 ,0xf957,0x3076 ,
+ 0xf8ca,0x30b8 ,0xf83c,0x30f9 ,0xf7ae,0x3139 ,
+ 0xf721,0x3179 ,0xf693,0x31b9 ,0xf606,0x31f8 ,
+ 0xf579,0x3236 ,0xf4ec,0x3274 ,0xf45f,0x32b2 ,
+ 0xf3d2,0x32ef ,0xf345,0x332c ,0xf2b8,0x3368 ,
+ 0xf22c,0x33a3 ,0xf19f,0x33df ,0xf113,0x3419 ,
+ 0xf087,0x3453 ,0xeffb,0x348d ,0xef6f,0x34c6 ,
+ 0xeee3,0x34ff ,0xee58,0x3537 ,0xedcc,0x356e ,
+ 0xed41,0x35a5 ,0xecb6,0x35dc ,0xec2b,0x3612 ,
+ 0xeba1,0x3648 ,0xeb16,0x367d ,0xea8c,0x36b1 ,
+ 0xea02,0x36e5 ,0xe978,0x3718 ,0xe8ef,0x374b ,
+ 0xe865,0x377e ,0xe7dc,0x37b0 ,0xe753,0x37e1 ,
+ 0xe6cb,0x3812 ,0xe642,0x3842 ,0xe5ba,0x3871 ,
+ 0xe532,0x38a1 ,0xe4aa,0x38cf ,0xe423,0x38fd ,
+ 0xe39c,0x392b ,0xe315,0x3958 ,0xe28e,0x3984 ,
+ 0xe208,0x39b0 ,0xe182,0x39db ,0xe0fc,0x3a06 ,
+ 0xe077,0x3a30 ,0xdff2,0x3a59 ,0xdf6d,0x3a82 ,
+ 0xdee9,0x3aab ,0xde64,0x3ad3 ,0xdde1,0x3afa ,
+ 0xdd5d,0x3b21 ,0xdcda,0x3b47 ,0xdc57,0x3b6d ,
+ 0xdbd5,0x3b92 ,0xdb52,0x3bb6 ,0xdad1,0x3bda ,
+ 0xda4f,0x3bfd ,0xd9ce,0x3c20 ,0xd94d,0x3c42 ,
+ 0xd8cd,0x3c64 ,0xd84d,0x3c85 ,0xd7cd,0x3ca5 ,
+ 0xd74e,0x3cc5 ,0xd6cf,0x3ce4 ,0xd651,0x3d03 ,
+ 0xd5d3,0x3d21 ,0xd556,0x3d3f ,0xd4d8,0x3d5b ,
+ 0xd45c,0x3d78 ,0xd3df,0x3d93 ,0xd363,0x3daf ,
+ 0xd2e8,0x3dc9 ,0xd26d,0x3de3 ,0xd1f2,0x3dfc ,
+ 0xd178,0x3e15 ,0xd0fe,0x3e2d ,0xd085,0x3e45 ,
+ 0xd00c,0x3e5c ,0xcf94,0x3e72 ,0xcf1c,0x3e88 ,
+ 0xcea5,0x3e9d ,0xce2e,0x3eb1 ,0xcdb7,0x3ec5 ,
+ 0xcd41,0x3ed8 ,0xcccc,0x3eeb ,0xcc57,0x3efd ,
+ 0xcbe2,0x3f0f ,0xcb6e,0x3f20 ,0xcafb,0x3f30 ,
+ 0xca88,0x3f40 ,0xca15,0x3f4f ,0xc9a3,0x3f5d ,
+ 0xc932,0x3f6b ,0xc8c1,0x3f78 ,0xc851,0x3f85 ,
+ 0xc7e1,0x3f91 ,0xc772,0x3f9c ,0xc703,0x3fa7 ,
+ 0xc695,0x3fb1 ,0xc627,0x3fbb ,0xc5ba,0x3fc4 ,
+ 0xc54e,0x3fcc ,0xc4e2,0x3fd4 ,0xc476,0x3fdb ,
+ 0xc40c,0x3fe1 ,0xc3a1,0x3fe7 ,0xc338,0x3fec ,
+ 0xc2cf,0x3ff1 ,0xc266,0x3ff5 ,0xc1fe,0x3ff8 ,
+ 0xc197,0x3ffb ,0xc130,0x3ffd ,0xc0ca,0x3fff ,
+ 0xc065,0x4000 ,0xc000,0x4000 ,0xbf9c,0x4000 ,
+ 0xbf38,0x3fff ,0xbed5,0x3ffd ,0xbe73,0x3ffb ,
+ 0xbe11,0x3ff8 ,0xbdb0,0x3ff5 ,0xbd50,0x3ff1 ,
+ 0xbcf0,0x3fec ,0xbc91,0x3fe7 ,0xbc32,0x3fe1 ,
+ 0xbbd4,0x3fdb ,0xbb77,0x3fd4 ,0xbb1b,0x3fcc ,
+ 0xbabf,0x3fc4 ,0xba64,0x3fbb ,0xba09,0x3fb1 ,
+ 0xb9af,0x3fa7 ,0xb956,0x3f9c ,0xb8fd,0x3f91 ,
+ 0xb8a6,0x3f85 ,0xb84f,0x3f78 ,0xb7f8,0x3f6b ,
+ 0xb7a2,0x3f5d ,0xb74d,0x3f4f ,0xb6f9,0x3f40 ,
+ 0xb6a5,0x3f30 ,0xb652,0x3f20 ,0xb600,0x3f0f ,
+ 0xb5af,0x3efd ,0xb55e,0x3eeb ,0xb50e,0x3ed8 ,
+ 0xb4be,0x3ec5 ,0xb470,0x3eb1 ,0xb422,0x3e9d ,
+ 0xb3d5,0x3e88 ,0xb388,0x3e72 ,0xb33d,0x3e5c ,
+ 0xb2f2,0x3e45 ,0xb2a7,0x3e2d ,0xb25e,0x3e15 ,
+ 0xb215,0x3dfc ,0xb1cd,0x3de3 ,0xb186,0x3dc9 ,
+ 0xb140,0x3daf ,0xb0fa,0x3d93 ,0xb0b5,0x3d78 ,
+ 0xb071,0x3d5b ,0xb02d,0x3d3f ,0xafeb,0x3d21 ,
+ 0xafa9,0x3d03 ,0xaf68,0x3ce4 ,0xaf28,0x3cc5 ,
+ 0xaee8,0x3ca5 ,0xaea9,0x3c85 ,0xae6b,0x3c64 ,
+ 0xae2e,0x3c42 ,0xadf2,0x3c20 ,0xadb6,0x3bfd ,
+ 0xad7b,0x3bda ,0xad41,0x3bb6 ,0xad08,0x3b92 ,
+ 0xacd0,0x3b6d ,0xac98,0x3b47 ,0xac61,0x3b21 ,
+ 0xac2b,0x3afa ,0xabf6,0x3ad3 ,0xabc2,0x3aab ,
+ 0xab8e,0x3a82 ,0xab5b,0x3a59 ,0xab29,0x3a30 ,
+ 0xaaf8,0x3a06 ,0xaac8,0x39db ,0xaa98,0x39b0 ,
+ 0xaa6a,0x3984 ,0xaa3c,0x3958 ,0xaa0f,0x392b ,
+ 0xa9e3,0x38fd ,0xa9b7,0x38cf ,0xa98d,0x38a1 ,
+ 0xa963,0x3871 ,0xa93a,0x3842 ,0xa912,0x3812 ,
+ 0xa8eb,0x37e1 ,0xa8c5,0x37b0 ,0xa89f,0x377e ,
+ 0xa87b,0x374b ,0xa857,0x3718 ,0xa834,0x36e5 ,
+ 0xa812,0x36b1 ,0xa7f1,0x367d ,0xa7d0,0x3648 ,
+ 0xa7b1,0x3612 ,0xa792,0x35dc ,0xa774,0x35a5 ,
+ 0xa757,0x356e ,0xa73b,0x3537 ,0xa71f,0x34ff ,
+ 0xa705,0x34c6 ,0xa6eb,0x348d ,0xa6d3,0x3453 ,
+ 0xa6bb,0x3419 ,0xa6a4,0x33df ,0xa68e,0x33a3 ,
+ 0xa678,0x3368 ,0xa664,0x332c ,0xa650,0x32ef ,
+ 0xa63e,0x32b2 ,0xa62c,0x3274 ,0xa61b,0x3236 ,
+ 0xa60b,0x31f8 ,0xa5fb,0x31b9 ,0xa5ed,0x3179 ,
+ 0xa5e0,0x3139 ,0xa5d3,0x30f9 ,0xa5c7,0x30b8 ,
+ 0xa5bc,0x3076 ,0xa5b2,0x3034 ,0xa5a9,0x2ff2 ,
+ 0xa5a1,0x2faf ,0xa599,0x2f6c ,0xa593,0x2f28 ,
+ 0xa58d,0x2ee4 ,0xa588,0x2e9f ,0xa585,0x2e5a ,
+ 0xa581,0x2e15 ,0xa57f,0x2dcf ,0xa57e,0x2d88 ,
+ 0xa57e,0x2d41 ,0xa57e,0x2cfa ,0xa57f,0x2cb2 ,
+ 0xa581,0x2c6a ,0xa585,0x2c21 ,0xa588,0x2bd8 ,
+ 0xa58d,0x2b8f ,0xa593,0x2b45 ,0xa599,0x2afb ,
+ 0xa5a1,0x2ab0 ,0xa5a9,0x2a65 ,0xa5b2,0x2a1a ,
+ 0xa5bc,0x29ce ,0xa5c7,0x2981 ,0xa5d3,0x2935 ,
+ 0xa5e0,0x28e7 ,0xa5ed,0x289a ,0xa5fb,0x284c ,
+ 0xa60b,0x27fe ,0xa61b,0x27af ,0xa62c,0x2760 ,
+ 0xa63e,0x2711 ,0xa650,0x26c1 ,0xa664,0x2671 ,
+ 0xa678,0x2620 ,0xa68e,0x25cf ,0xa6a4,0x257e ,
+ 0xa6bb,0x252c ,0xa6d3,0x24da ,0xa6eb,0x2488 ,
+ 0xa705,0x2435 ,0xa71f,0x23e2 ,0xa73b,0x238e ,
+ 0xa757,0x233b ,0xa774,0x22e7 ,0xa792,0x2292 ,
+ 0xa7b1,0x223d ,0xa7d0,0x21e8 ,0xa7f1,0x2193 ,
+ 0xa812,0x213d ,0xa834,0x20e7 ,0xa857,0x2091 ,
+ 0xa87b,0x203a ,0xa89f,0x1fe3 ,0xa8c5,0x1f8c ,
+ 0xa8eb,0x1f34 ,0xa912,0x1edc ,0xa93a,0x1e84 ,
+ 0xa963,0x1e2b ,0xa98d,0x1dd3 ,0xa9b7,0x1d79 ,
+ 0xa9e3,0x1d20 ,0xaa0f,0x1cc6 ,0xaa3c,0x1c6c ,
+ 0xaa6a,0x1c12 ,0xaa98,0x1bb8 ,0xaac8,0x1b5d ,
+ 0xaaf8,0x1b02 ,0xab29,0x1aa7 ,0xab5b,0x1a4b ,
+ 0xab8e,0x19ef ,0xabc2,0x1993 ,0xabf6,0x1937 ,
+ 0xac2b,0x18db ,0xac61,0x187e ,0xac98,0x1821 ,
+ 0xacd0,0x17c4 ,0xad08,0x1766 ,0xad41,0x1709 ,
+ 0xad7b,0x16ab ,0xadb6,0x164c ,0xadf2,0x15ee ,
+ 0xae2e,0x1590 ,0xae6b,0x1531 ,0xaea9,0x14d2 ,
+ 0xaee8,0x1473 ,0xaf28,0x1413 ,0xaf68,0x13b4 ,
+ 0xafa9,0x1354 ,0xafeb,0x12f4 ,0xb02d,0x1294 ,
+ 0xb071,0x1234 ,0xb0b5,0x11d3 ,0xb0fa,0x1173 ,
+ 0xb140,0x1112 ,0xb186,0x10b1 ,0xb1cd,0x1050 ,
+ 0xb215,0x0fee ,0xb25e,0x0f8d ,0xb2a7,0x0f2b ,
+ 0xb2f2,0x0eca ,0xb33d,0x0e68 ,0xb388,0x0e06 ,
+ 0xb3d5,0x0da4 ,0xb422,0x0d41 ,0xb470,0x0cdf ,
+ 0xb4be,0x0c7c ,0xb50e,0x0c1a ,0xb55e,0x0bb7 ,
+ 0xb5af,0x0b54 ,0xb600,0x0af1 ,0xb652,0x0a8e ,
+ 0xb6a5,0x0a2b ,0xb6f9,0x09c7 ,0xb74d,0x0964 ,
+ 0xb7a2,0x0901 ,0xb7f8,0x089d ,0xb84f,0x0839 ,
+ 0xb8a6,0x07d6 ,0xb8fd,0x0772 ,0xb956,0x070e ,
+ 0xb9af,0x06aa ,0xba09,0x0646 ,0xba64,0x05e2 ,
+ 0xbabf,0x057e ,0xbb1b,0x051a ,0xbb77,0x04b5 ,
+ 0xbbd4,0x0451 ,0xbc32,0x03ed ,0xbc91,0x0388 ,
+ 0xbcf0,0x0324 ,0xbd50,0x02c0 ,0xbdb0,0x025b ,
+ 0xbe11,0x01f7 ,0xbe73,0x0192 ,0xbed5,0x012e ,
+ 0xbf38,0x00c9 ,0xbf9c,0x0065 };
+
+
+extern const int s_Q14R_8;
+const int s_Q14R_8 = 1024;
+extern const unsigned short t_Q14R_8[2032];
+const unsigned short t_Q14R_8[2032] = {
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3fb1,0x0646 ,0x3fec,0x0324 ,0x3f4f,0x0964 ,
+ 0x3ec5,0x0c7c ,0x3fb1,0x0646 ,0x3d3f,0x1294 ,
+ 0x3d3f,0x1294 ,0x3f4f,0x0964 ,0x39db,0x1b5d ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x3871,0x1e2b ,0x3e15,0x0f8d ,0x2f6c,0x2afb ,
+ 0x3537,0x238e ,0x3d3f,0x1294 ,0x289a,0x3179 ,
+ 0x3179,0x289a ,0x3c42,0x1590 ,0x20e7,0x36e5 ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x289a,0x3179 ,0x39db,0x1b5d ,0x0f8d,0x3e15 ,
+ 0x238e,0x3537 ,0x3871,0x1e2b ,0x0646,0x3fb1 ,
+ 0x1e2b,0x3871 ,0x36e5,0x20e7 ,0xfcdc,0x3fec ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x1294,0x3d3f ,0x3368,0x2620 ,0xea70,0x3c42 ,
+ 0x0c7c,0x3ec5 ,0x3179,0x289a ,0xe1d5,0x3871 ,
+ 0x0646,0x3fb1 ,0x2f6c,0x2afb ,0xd9e0,0x3368 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xf9ba,0x3fb1 ,0x2afb,0x2f6c ,0xcc98,0x2620 ,
+ 0xf384,0x3ec5 ,0x289a,0x3179 ,0xc78f,0x1e2b ,
+ 0xed6c,0x3d3f ,0x2620,0x3368 ,0xc3be,0x1590 ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xe1d5,0x3871 ,0x20e7,0x36e5 ,0xc014,0x0324 ,
+ 0xdc72,0x3537 ,0x1e2b,0x3871 ,0xc04f,0xf9ba ,
+ 0xd766,0x3179 ,0x1b5d,0x39db ,0xc1eb,0xf073 ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xce87,0x289a ,0x1590,0x3c42 ,0xc91b,0xdf19 ,
+ 0xcac9,0x238e ,0x1294,0x3d3f ,0xce87,0xd766 ,
+ 0xc78f,0x1e2b ,0x0f8d,0x3e15 ,0xd505,0xd094 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0xc2c1,0x1294 ,0x0964,0x3f4f ,0xe4a3,0xc625 ,
+ 0xc13b,0x0c7c ,0x0646,0x3fb1 ,0xed6c,0xc2c1 ,
+ 0xc04f,0x0646 ,0x0324,0x3fec ,0xf69c,0xc0b1 ,
+ 0x4000,0x0000 ,0x4000,0x0000 ,0x4000,0x0000 ,
+ 0x3ffb,0x0192 ,0x3fff,0x00c9 ,0x3ff5,0x025b ,
+ 0x3fec,0x0324 ,0x3ffb,0x0192 ,0x3fd4,0x04b5 ,
+ 0x3fd4,0x04b5 ,0x3ff5,0x025b ,0x3f9c,0x070e ,
+ 0x3fb1,0x0646 ,0x3fec,0x0324 ,0x3f4f,0x0964 ,
+ 0x3f85,0x07d6 ,0x3fe1,0x03ed ,0x3eeb,0x0bb7 ,
+ 0x3f4f,0x0964 ,0x3fd4,0x04b5 ,0x3e72,0x0e06 ,
+ 0x3f0f,0x0af1 ,0x3fc4,0x057e ,0x3de3,0x1050 ,
+ 0x3ec5,0x0c7c ,0x3fb1,0x0646 ,0x3d3f,0x1294 ,
+ 0x3e72,0x0e06 ,0x3f9c,0x070e ,0x3c85,0x14d2 ,
+ 0x3e15,0x0f8d ,0x3f85,0x07d6 ,0x3bb6,0x1709 ,
+ 0x3daf,0x1112 ,0x3f6b,0x089d ,0x3ad3,0x1937 ,
+ 0x3d3f,0x1294 ,0x3f4f,0x0964 ,0x39db,0x1b5d ,
+ 0x3cc5,0x1413 ,0x3f30,0x0a2b ,0x38cf,0x1d79 ,
+ 0x3c42,0x1590 ,0x3f0f,0x0af1 ,0x37b0,0x1f8c ,
+ 0x3bb6,0x1709 ,0x3eeb,0x0bb7 ,0x367d,0x2193 ,
+ 0x3b21,0x187e ,0x3ec5,0x0c7c ,0x3537,0x238e ,
+ 0x3a82,0x19ef ,0x3e9d,0x0d41 ,0x33df,0x257e ,
+ 0x39db,0x1b5d ,0x3e72,0x0e06 ,0x3274,0x2760 ,
+ 0x392b,0x1cc6 ,0x3e45,0x0eca ,0x30f9,0x2935 ,
+ 0x3871,0x1e2b ,0x3e15,0x0f8d ,0x2f6c,0x2afb ,
+ 0x37b0,0x1f8c ,0x3de3,0x1050 ,0x2dcf,0x2cb2 ,
+ 0x36e5,0x20e7 ,0x3daf,0x1112 ,0x2c21,0x2e5a ,
+ 0x3612,0x223d ,0x3d78,0x11d3 ,0x2a65,0x2ff2 ,
+ 0x3537,0x238e ,0x3d3f,0x1294 ,0x289a,0x3179 ,
+ 0x3453,0x24da ,0x3d03,0x1354 ,0x26c1,0x32ef ,
+ 0x3368,0x2620 ,0x3cc5,0x1413 ,0x24da,0x3453 ,
+ 0x3274,0x2760 ,0x3c85,0x14d2 ,0x22e7,0x35a5 ,
+ 0x3179,0x289a ,0x3c42,0x1590 ,0x20e7,0x36e5 ,
+ 0x3076,0x29ce ,0x3bfd,0x164c ,0x1edc,0x3812 ,
+ 0x2f6c,0x2afb ,0x3bb6,0x1709 ,0x1cc6,0x392b ,
+ 0x2e5a,0x2c21 ,0x3b6d,0x17c4 ,0x1aa7,0x3a30 ,
+ 0x2d41,0x2d41 ,0x3b21,0x187e ,0x187e,0x3b21 ,
+ 0x2c21,0x2e5a ,0x3ad3,0x1937 ,0x164c,0x3bfd ,
+ 0x2afb,0x2f6c ,0x3a82,0x19ef ,0x1413,0x3cc5 ,
+ 0x29ce,0x3076 ,0x3a30,0x1aa7 ,0x11d3,0x3d78 ,
+ 0x289a,0x3179 ,0x39db,0x1b5d ,0x0f8d,0x3e15 ,
+ 0x2760,0x3274 ,0x3984,0x1c12 ,0x0d41,0x3e9d ,
+ 0x2620,0x3368 ,0x392b,0x1cc6 ,0x0af1,0x3f0f ,
+ 0x24da,0x3453 ,0x38cf,0x1d79 ,0x089d,0x3f6b ,
+ 0x238e,0x3537 ,0x3871,0x1e2b ,0x0646,0x3fb1 ,
+ 0x223d,0x3612 ,0x3812,0x1edc ,0x03ed,0x3fe1 ,
+ 0x20e7,0x36e5 ,0x37b0,0x1f8c ,0x0192,0x3ffb ,
+ 0x1f8c,0x37b0 ,0x374b,0x203a ,0xff37,0x3fff ,
+ 0x1e2b,0x3871 ,0x36e5,0x20e7 ,0xfcdc,0x3fec ,
+ 0x1cc6,0x392b ,0x367d,0x2193 ,0xfa82,0x3fc4 ,
+ 0x1b5d,0x39db ,0x3612,0x223d ,0xf82a,0x3f85 ,
+ 0x19ef,0x3a82 ,0x35a5,0x22e7 ,0xf5d5,0x3f30 ,
+ 0x187e,0x3b21 ,0x3537,0x238e ,0xf384,0x3ec5 ,
+ 0x1709,0x3bb6 ,0x34c6,0x2435 ,0xf136,0x3e45 ,
+ 0x1590,0x3c42 ,0x3453,0x24da ,0xeeee,0x3daf ,
+ 0x1413,0x3cc5 ,0x33df,0x257e ,0xecac,0x3d03 ,
+ 0x1294,0x3d3f ,0x3368,0x2620 ,0xea70,0x3c42 ,
+ 0x1112,0x3daf ,0x32ef,0x26c1 ,0xe83c,0x3b6d ,
+ 0x0f8d,0x3e15 ,0x3274,0x2760 ,0xe611,0x3a82 ,
+ 0x0e06,0x3e72 ,0x31f8,0x27fe ,0xe3ee,0x3984 ,
+ 0x0c7c,0x3ec5 ,0x3179,0x289a ,0xe1d5,0x3871 ,
+ 0x0af1,0x3f0f ,0x30f9,0x2935 ,0xdfc6,0x374b ,
+ 0x0964,0x3f4f ,0x3076,0x29ce ,0xddc3,0x3612 ,
+ 0x07d6,0x3f85 ,0x2ff2,0x2a65 ,0xdbcb,0x34c6 ,
+ 0x0646,0x3fb1 ,0x2f6c,0x2afb ,0xd9e0,0x3368 ,
+ 0x04b5,0x3fd4 ,0x2ee4,0x2b8f ,0xd802,0x31f8 ,
+ 0x0324,0x3fec ,0x2e5a,0x2c21 ,0xd632,0x3076 ,
+ 0x0192,0x3ffb ,0x2dcf,0x2cb2 ,0xd471,0x2ee4 ,
+ 0x0000,0x4000 ,0x2d41,0x2d41 ,0xd2bf,0x2d41 ,
+ 0xfe6e,0x3ffb ,0x2cb2,0x2dcf ,0xd11c,0x2b8f ,
+ 0xfcdc,0x3fec ,0x2c21,0x2e5a ,0xcf8a,0x29ce ,
+ 0xfb4b,0x3fd4 ,0x2b8f,0x2ee4 ,0xce08,0x27fe ,
+ 0xf9ba,0x3fb1 ,0x2afb,0x2f6c ,0xcc98,0x2620 ,
+ 0xf82a,0x3f85 ,0x2a65,0x2ff2 ,0xcb3a,0x2435 ,
+ 0xf69c,0x3f4f ,0x29ce,0x3076 ,0xc9ee,0x223d ,
+ 0xf50f,0x3f0f ,0x2935,0x30f9 ,0xc8b5,0x203a ,
+ 0xf384,0x3ec5 ,0x289a,0x3179 ,0xc78f,0x1e2b ,
+ 0xf1fa,0x3e72 ,0x27fe,0x31f8 ,0xc67c,0x1c12 ,
+ 0xf073,0x3e15 ,0x2760,0x3274 ,0xc57e,0x19ef ,
+ 0xeeee,0x3daf ,0x26c1,0x32ef ,0xc493,0x17c4 ,
+ 0xed6c,0x3d3f ,0x2620,0x3368 ,0xc3be,0x1590 ,
+ 0xebed,0x3cc5 ,0x257e,0x33df ,0xc2fd,0x1354 ,
+ 0xea70,0x3c42 ,0x24da,0x3453 ,0xc251,0x1112 ,
+ 0xe8f7,0x3bb6 ,0x2435,0x34c6 ,0xc1bb,0x0eca ,
+ 0xe782,0x3b21 ,0x238e,0x3537 ,0xc13b,0x0c7c ,
+ 0xe611,0x3a82 ,0x22e7,0x35a5 ,0xc0d0,0x0a2b ,
+ 0xe4a3,0x39db ,0x223d,0x3612 ,0xc07b,0x07d6 ,
+ 0xe33a,0x392b ,0x2193,0x367d ,0xc03c,0x057e ,
+ 0xe1d5,0x3871 ,0x20e7,0x36e5 ,0xc014,0x0324 ,
+ 0xe074,0x37b0 ,0x203a,0x374b ,0xc001,0x00c9 ,
+ 0xdf19,0x36e5 ,0x1f8c,0x37b0 ,0xc005,0xfe6e ,
+ 0xddc3,0x3612 ,0x1edc,0x3812 ,0xc01f,0xfc13 ,
+ 0xdc72,0x3537 ,0x1e2b,0x3871 ,0xc04f,0xf9ba ,
+ 0xdb26,0x3453 ,0x1d79,0x38cf ,0xc095,0xf763 ,
+ 0xd9e0,0x3368 ,0x1cc6,0x392b ,0xc0f1,0xf50f ,
+ 0xd8a0,0x3274 ,0x1c12,0x3984 ,0xc163,0xf2bf ,
+ 0xd766,0x3179 ,0x1b5d,0x39db ,0xc1eb,0xf073 ,
+ 0xd632,0x3076 ,0x1aa7,0x3a30 ,0xc288,0xee2d ,
+ 0xd505,0x2f6c ,0x19ef,0x3a82 ,0xc33b,0xebed ,
+ 0xd3df,0x2e5a ,0x1937,0x3ad3 ,0xc403,0xe9b4 ,
+ 0xd2bf,0x2d41 ,0x187e,0x3b21 ,0xc4df,0xe782 ,
+ 0xd1a6,0x2c21 ,0x17c4,0x3b6d ,0xc5d0,0xe559 ,
+ 0xd094,0x2afb ,0x1709,0x3bb6 ,0xc6d5,0xe33a ,
+ 0xcf8a,0x29ce ,0x164c,0x3bfd ,0xc7ee,0xe124 ,
+ 0xce87,0x289a ,0x1590,0x3c42 ,0xc91b,0xdf19 ,
+ 0xcd8c,0x2760 ,0x14d2,0x3c85 ,0xca5b,0xdd19 ,
+ 0xcc98,0x2620 ,0x1413,0x3cc5 ,0xcbad,0xdb26 ,
+ 0xcbad,0x24da ,0x1354,0x3d03 ,0xcd11,0xd93f ,
+ 0xcac9,0x238e ,0x1294,0x3d3f ,0xce87,0xd766 ,
+ 0xc9ee,0x223d ,0x11d3,0x3d78 ,0xd00e,0xd59b ,
+ 0xc91b,0x20e7 ,0x1112,0x3daf ,0xd1a6,0xd3df ,
+ 0xc850,0x1f8c ,0x1050,0x3de3 ,0xd34e,0xd231 ,
+ 0xc78f,0x1e2b ,0x0f8d,0x3e15 ,0xd505,0xd094 ,
+ 0xc6d5,0x1cc6 ,0x0eca,0x3e45 ,0xd6cb,0xcf07 ,
+ 0xc625,0x1b5d ,0x0e06,0x3e72 ,0xd8a0,0xcd8c ,
+ 0xc57e,0x19ef ,0x0d41,0x3e9d ,0xda82,0xcc21 ,
+ 0xc4df,0x187e ,0x0c7c,0x3ec5 ,0xdc72,0xcac9 ,
+ 0xc44a,0x1709 ,0x0bb7,0x3eeb ,0xde6d,0xc983 ,
+ 0xc3be,0x1590 ,0x0af1,0x3f0f ,0xe074,0xc850 ,
+ 0xc33b,0x1413 ,0x0a2b,0x3f30 ,0xe287,0xc731 ,
+ 0xc2c1,0x1294 ,0x0964,0x3f4f ,0xe4a3,0xc625 ,
+ 0xc251,0x1112 ,0x089d,0x3f6b ,0xe6c9,0xc52d ,
+ 0xc1eb,0x0f8d ,0x07d6,0x3f85 ,0xe8f7,0xc44a ,
+ 0xc18e,0x0e06 ,0x070e,0x3f9c ,0xeb2e,0xc37b ,
+ 0xc13b,0x0c7c ,0x0646,0x3fb1 ,0xed6c,0xc2c1 ,
+ 0xc0f1,0x0af1 ,0x057e,0x3fc4 ,0xefb0,0xc21d ,
+ 0xc0b1,0x0964 ,0x04b5,0x3fd4 ,0xf1fa,0xc18e ,
+ 0xc07b,0x07d6 ,0x03ed,0x3fe1 ,0xf449,0xc115 ,
+ 0xc04f,0x0646 ,0x0324,0x3fec ,0xf69c,0xc0b1 ,
+ 0xc02c,0x04b5 ,0x025b,0x3ff5 ,0xf8f2,0xc064 ,
+ 0xc014,0x0324 ,0x0192,0x3ffb ,0xfb4b,0xc02c ,
+ 0xc005,0x0192 ,0x00c9,0x3fff ,0xfda5,0xc00b ,
+ 0x4000,0x0000 ,0x4000,0x0065 ,0x3fff,0x00c9 ,
+ 0x3ffd,0x012e ,0x3ffb,0x0192 ,0x3ff8,0x01f7 ,
+ 0x3ff5,0x025b ,0x3ff1,0x02c0 ,0x3fec,0x0324 ,
+ 0x3fe7,0x0388 ,0x3fe1,0x03ed ,0x3fdb,0x0451 ,
+ 0x3fd4,0x04b5 ,0x3fcc,0x051a ,0x3fc4,0x057e ,
+ 0x3fbb,0x05e2 ,0x3fb1,0x0646 ,0x3fa7,0x06aa ,
+ 0x3f9c,0x070e ,0x3f91,0x0772 ,0x3f85,0x07d6 ,
+ 0x3f78,0x0839 ,0x3f6b,0x089d ,0x3f5d,0x0901 ,
+ 0x3f4f,0x0964 ,0x3f40,0x09c7 ,0x3f30,0x0a2b ,
+ 0x3f20,0x0a8e ,0x3f0f,0x0af1 ,0x3efd,0x0b54 ,
+ 0x3eeb,0x0bb7 ,0x3ed8,0x0c1a ,0x3ec5,0x0c7c ,
+ 0x3eb1,0x0cdf ,0x3e9d,0x0d41 ,0x3e88,0x0da4 ,
+ 0x3e72,0x0e06 ,0x3e5c,0x0e68 ,0x3e45,0x0eca ,
+ 0x3e2d,0x0f2b ,0x3e15,0x0f8d ,0x3dfc,0x0fee ,
+ 0x3de3,0x1050 ,0x3dc9,0x10b1 ,0x3daf,0x1112 ,
+ 0x3d93,0x1173 ,0x3d78,0x11d3 ,0x3d5b,0x1234 ,
+ 0x3d3f,0x1294 ,0x3d21,0x12f4 ,0x3d03,0x1354 ,
+ 0x3ce4,0x13b4 ,0x3cc5,0x1413 ,0x3ca5,0x1473 ,
+ 0x3c85,0x14d2 ,0x3c64,0x1531 ,0x3c42,0x1590 ,
+ 0x3c20,0x15ee ,0x3bfd,0x164c ,0x3bda,0x16ab ,
+ 0x3bb6,0x1709 ,0x3b92,0x1766 ,0x3b6d,0x17c4 ,
+ 0x3b47,0x1821 ,0x3b21,0x187e ,0x3afa,0x18db ,
+ 0x3ad3,0x1937 ,0x3aab,0x1993 ,0x3a82,0x19ef ,
+ 0x3a59,0x1a4b ,0x3a30,0x1aa7 ,0x3a06,0x1b02 ,
+ 0x39db,0x1b5d ,0x39b0,0x1bb8 ,0x3984,0x1c12 ,
+ 0x3958,0x1c6c ,0x392b,0x1cc6 ,0x38fd,0x1d20 ,
+ 0x38cf,0x1d79 ,0x38a1,0x1dd3 ,0x3871,0x1e2b ,
+ 0x3842,0x1e84 ,0x3812,0x1edc ,0x37e1,0x1f34 ,
+ 0x37b0,0x1f8c ,0x377e,0x1fe3 ,0x374b,0x203a ,
+ 0x3718,0x2091 ,0x36e5,0x20e7 ,0x36b1,0x213d ,
+ 0x367d,0x2193 ,0x3648,0x21e8 ,0x3612,0x223d ,
+ 0x35dc,0x2292 ,0x35a5,0x22e7 ,0x356e,0x233b ,
+ 0x3537,0x238e ,0x34ff,0x23e2 ,0x34c6,0x2435 ,
+ 0x348d,0x2488 ,0x3453,0x24da ,0x3419,0x252c ,
+ 0x33df,0x257e ,0x33a3,0x25cf ,0x3368,0x2620 ,
+ 0x332c,0x2671 ,0x32ef,0x26c1 ,0x32b2,0x2711 ,
+ 0x3274,0x2760 ,0x3236,0x27af ,0x31f8,0x27fe ,
+ 0x31b9,0x284c ,0x3179,0x289a ,0x3139,0x28e7 ,
+ 0x30f9,0x2935 ,0x30b8,0x2981 ,0x3076,0x29ce ,
+ 0x3034,0x2a1a ,0x2ff2,0x2a65 ,0x2faf,0x2ab0 ,
+ 0x2f6c,0x2afb ,0x2f28,0x2b45 ,0x2ee4,0x2b8f ,
+ 0x2e9f,0x2bd8 ,0x2e5a,0x2c21 ,0x2e15,0x2c6a ,
+ 0x2dcf,0x2cb2 ,0x2d88,0x2cfa ,0x2d41,0x2d41 ,
+ 0x2cfa,0x2d88 ,0x2cb2,0x2dcf ,0x2c6a,0x2e15 ,
+ 0x2c21,0x2e5a ,0x2bd8,0x2e9f ,0x2b8f,0x2ee4 ,
+ 0x2b45,0x2f28 ,0x2afb,0x2f6c ,0x2ab0,0x2faf ,
+ 0x2a65,0x2ff2 ,0x2a1a,0x3034 ,0x29ce,0x3076 ,
+ 0x2981,0x30b8 ,0x2935,0x30f9 ,0x28e7,0x3139 ,
+ 0x289a,0x3179 ,0x284c,0x31b9 ,0x27fe,0x31f8 ,
+ 0x27af,0x3236 ,0x2760,0x3274 ,0x2711,0x32b2 ,
+ 0x26c1,0x32ef ,0x2671,0x332c ,0x2620,0x3368 ,
+ 0x25cf,0x33a3 ,0x257e,0x33df ,0x252c,0x3419 ,
+ 0x24da,0x3453 ,0x2488,0x348d ,0x2435,0x34c6 ,
+ 0x23e2,0x34ff ,0x238e,0x3537 ,0x233b,0x356e ,
+ 0x22e7,0x35a5 ,0x2292,0x35dc ,0x223d,0x3612 ,
+ 0x21e8,0x3648 ,0x2193,0x367d ,0x213d,0x36b1 ,
+ 0x20e7,0x36e5 ,0x2091,0x3718 ,0x203a,0x374b ,
+ 0x1fe3,0x377e ,0x1f8c,0x37b0 ,0x1f34,0x37e1 ,
+ 0x1edc,0x3812 ,0x1e84,0x3842 ,0x1e2b,0x3871 ,
+ 0x1dd3,0x38a1 ,0x1d79,0x38cf ,0x1d20,0x38fd ,
+ 0x1cc6,0x392b ,0x1c6c,0x3958 ,0x1c12,0x3984 ,
+ 0x1bb8,0x39b0 ,0x1b5d,0x39db ,0x1b02,0x3a06 ,
+ 0x1aa7,0x3a30 ,0x1a4b,0x3a59 ,0x19ef,0x3a82 ,
+ 0x1993,0x3aab ,0x1937,0x3ad3 ,0x18db,0x3afa ,
+ 0x187e,0x3b21 ,0x1821,0x3b47 ,0x17c4,0x3b6d ,
+ 0x1766,0x3b92 ,0x1709,0x3bb6 ,0x16ab,0x3bda ,
+ 0x164c,0x3bfd ,0x15ee,0x3c20 ,0x1590,0x3c42 ,
+ 0x1531,0x3c64 ,0x14d2,0x3c85 ,0x1473,0x3ca5 ,
+ 0x1413,0x3cc5 ,0x13b4,0x3ce4 ,0x1354,0x3d03 ,
+ 0x12f4,0x3d21 ,0x1294,0x3d3f ,0x1234,0x3d5b ,
+ 0x11d3,0x3d78 ,0x1173,0x3d93 ,0x1112,0x3daf ,
+ 0x10b1,0x3dc9 ,0x1050,0x3de3 ,0x0fee,0x3dfc ,
+ 0x0f8d,0x3e15 ,0x0f2b,0x3e2d ,0x0eca,0x3e45 ,
+ 0x0e68,0x3e5c ,0x0e06,0x3e72 ,0x0da4,0x3e88 ,
+ 0x0d41,0x3e9d ,0x0cdf,0x3eb1 ,0x0c7c,0x3ec5 ,
+ 0x0c1a,0x3ed8 ,0x0bb7,0x3eeb ,0x0b54,0x3efd ,
+ 0x0af1,0x3f0f ,0x0a8e,0x3f20 ,0x0a2b,0x3f30 ,
+ 0x09c7,0x3f40 ,0x0964,0x3f4f ,0x0901,0x3f5d ,
+ 0x089d,0x3f6b ,0x0839,0x3f78 ,0x07d6,0x3f85 ,
+ 0x0772,0x3f91 ,0x070e,0x3f9c ,0x06aa,0x3fa7 ,
+ 0x0646,0x3fb1 ,0x05e2,0x3fbb ,0x057e,0x3fc4 ,
+ 0x051a,0x3fcc ,0x04b5,0x3fd4 ,0x0451,0x3fdb ,
+ 0x03ed,0x3fe1 ,0x0388,0x3fe7 ,0x0324,0x3fec ,
+ 0x02c0,0x3ff1 ,0x025b,0x3ff5 ,0x01f7,0x3ff8 ,
+ 0x0192,0x3ffb ,0x012e,0x3ffd ,0x00c9,0x3fff ,
+ 0x0065,0x4000 ,0x0000,0x4000 ,0xff9b,0x4000 ,
+ 0xff37,0x3fff ,0xfed2,0x3ffd ,0xfe6e,0x3ffb ,
+ 0xfe09,0x3ff8 ,0xfda5,0x3ff5 ,0xfd40,0x3ff1 ,
+ 0xfcdc,0x3fec ,0xfc78,0x3fe7 ,0xfc13,0x3fe1 ,
+ 0xfbaf,0x3fdb ,0xfb4b,0x3fd4 ,0xfae6,0x3fcc ,
+ 0xfa82,0x3fc4 ,0xfa1e,0x3fbb ,0xf9ba,0x3fb1 ,
+ 0xf956,0x3fa7 ,0xf8f2,0x3f9c ,0xf88e,0x3f91 ,
+ 0xf82a,0x3f85 ,0xf7c7,0x3f78 ,0xf763,0x3f6b ,
+ 0xf6ff,0x3f5d ,0xf69c,0x3f4f ,0xf639,0x3f40 ,
+ 0xf5d5,0x3f30 ,0xf572,0x3f20 ,0xf50f,0x3f0f ,
+ 0xf4ac,0x3efd ,0xf449,0x3eeb ,0xf3e6,0x3ed8 ,
+ 0xf384,0x3ec5 ,0xf321,0x3eb1 ,0xf2bf,0x3e9d ,
+ 0xf25c,0x3e88 ,0xf1fa,0x3e72 ,0xf198,0x3e5c ,
+ 0xf136,0x3e45 ,0xf0d5,0x3e2d ,0xf073,0x3e15 ,
+ 0xf012,0x3dfc ,0xefb0,0x3de3 ,0xef4f,0x3dc9 ,
+ 0xeeee,0x3daf ,0xee8d,0x3d93 ,0xee2d,0x3d78 ,
+ 0xedcc,0x3d5b ,0xed6c,0x3d3f ,0xed0c,0x3d21 ,
+ 0xecac,0x3d03 ,0xec4c,0x3ce4 ,0xebed,0x3cc5 ,
+ 0xeb8d,0x3ca5 ,0xeb2e,0x3c85 ,0xeacf,0x3c64 ,
+ 0xea70,0x3c42 ,0xea12,0x3c20 ,0xe9b4,0x3bfd ,
+ 0xe955,0x3bda ,0xe8f7,0x3bb6 ,0xe89a,0x3b92 ,
+ 0xe83c,0x3b6d ,0xe7df,0x3b47 ,0xe782,0x3b21 ,
+ 0xe725,0x3afa ,0xe6c9,0x3ad3 ,0xe66d,0x3aab ,
+ 0xe611,0x3a82 ,0xe5b5,0x3a59 ,0xe559,0x3a30 ,
+ 0xe4fe,0x3a06 ,0xe4a3,0x39db ,0xe448,0x39b0 ,
+ 0xe3ee,0x3984 ,0xe394,0x3958 ,0xe33a,0x392b ,
+ 0xe2e0,0x38fd ,0xe287,0x38cf ,0xe22d,0x38a1 ,
+ 0xe1d5,0x3871 ,0xe17c,0x3842 ,0xe124,0x3812 ,
+ 0xe0cc,0x37e1 ,0xe074,0x37b0 ,0xe01d,0x377e ,
+ 0xdfc6,0x374b ,0xdf6f,0x3718 ,0xdf19,0x36e5 ,
+ 0xdec3,0x36b1 ,0xde6d,0x367d ,0xde18,0x3648 ,
+ 0xddc3,0x3612 ,0xdd6e,0x35dc ,0xdd19,0x35a5 ,
+ 0xdcc5,0x356e ,0xdc72,0x3537 ,0xdc1e,0x34ff ,
+ 0xdbcb,0x34c6 ,0xdb78,0x348d ,0xdb26,0x3453 ,
+ 0xdad4,0x3419 ,0xda82,0x33df ,0xda31,0x33a3 ,
+ 0xd9e0,0x3368 ,0xd98f,0x332c ,0xd93f,0x32ef ,
+ 0xd8ef,0x32b2 ,0xd8a0,0x3274 ,0xd851,0x3236 ,
+ 0xd802,0x31f8 ,0xd7b4,0x31b9 ,0xd766,0x3179 ,
+ 0xd719,0x3139 ,0xd6cb,0x30f9 ,0xd67f,0x30b8 ,
+ 0xd632,0x3076 ,0xd5e6,0x3034 ,0xd59b,0x2ff2 ,
+ 0xd550,0x2faf ,0xd505,0x2f6c ,0xd4bb,0x2f28 ,
+ 0xd471,0x2ee4 ,0xd428,0x2e9f ,0xd3df,0x2e5a ,
+ 0xd396,0x2e15 ,0xd34e,0x2dcf ,0xd306,0x2d88 ,
+ 0xd2bf,0x2d41 ,0xd278,0x2cfa ,0xd231,0x2cb2 ,
+ 0xd1eb,0x2c6a ,0xd1a6,0x2c21 ,0xd161,0x2bd8 ,
+ 0xd11c,0x2b8f ,0xd0d8,0x2b45 ,0xd094,0x2afb ,
+ 0xd051,0x2ab0 ,0xd00e,0x2a65 ,0xcfcc,0x2a1a ,
+ 0xcf8a,0x29ce ,0xcf48,0x2981 ,0xcf07,0x2935 ,
+ 0xcec7,0x28e7 ,0xce87,0x289a ,0xce47,0x284c ,
+ 0xce08,0x27fe ,0xcdca,0x27af ,0xcd8c,0x2760 ,
+ 0xcd4e,0x2711 ,0xcd11,0x26c1 ,0xccd4,0x2671 ,
+ 0xcc98,0x2620 ,0xcc5d,0x25cf ,0xcc21,0x257e ,
+ 0xcbe7,0x252c ,0xcbad,0x24da ,0xcb73,0x2488 ,
+ 0xcb3a,0x2435 ,0xcb01,0x23e2 ,0xcac9,0x238e ,
+ 0xca92,0x233b ,0xca5b,0x22e7 ,0xca24,0x2292 ,
+ 0xc9ee,0x223d ,0xc9b8,0x21e8 ,0xc983,0x2193 ,
+ 0xc94f,0x213d ,0xc91b,0x20e7 ,0xc8e8,0x2091 ,
+ 0xc8b5,0x203a ,0xc882,0x1fe3 ,0xc850,0x1f8c ,
+ 0xc81f,0x1f34 ,0xc7ee,0x1edc ,0xc7be,0x1e84 ,
+ 0xc78f,0x1e2b ,0xc75f,0x1dd3 ,0xc731,0x1d79 ,
+ 0xc703,0x1d20 ,0xc6d5,0x1cc6 ,0xc6a8,0x1c6c ,
+ 0xc67c,0x1c12 ,0xc650,0x1bb8 ,0xc625,0x1b5d ,
+ 0xc5fa,0x1b02 ,0xc5d0,0x1aa7 ,0xc5a7,0x1a4b ,
+ 0xc57e,0x19ef ,0xc555,0x1993 ,0xc52d,0x1937 ,
+ 0xc506,0x18db ,0xc4df,0x187e ,0xc4b9,0x1821 ,
+ 0xc493,0x17c4 ,0xc46e,0x1766 ,0xc44a,0x1709 ,
+ 0xc426,0x16ab ,0xc403,0x164c ,0xc3e0,0x15ee ,
+ 0xc3be,0x1590 ,0xc39c,0x1531 ,0xc37b,0x14d2 ,
+ 0xc35b,0x1473 ,0xc33b,0x1413 ,0xc31c,0x13b4 ,
+ 0xc2fd,0x1354 ,0xc2df,0x12f4 ,0xc2c1,0x1294 ,
+ 0xc2a5,0x1234 ,0xc288,0x11d3 ,0xc26d,0x1173 ,
+ 0xc251,0x1112 ,0xc237,0x10b1 ,0xc21d,0x1050 ,
+ 0xc204,0x0fee ,0xc1eb,0x0f8d ,0xc1d3,0x0f2b ,
+ 0xc1bb,0x0eca ,0xc1a4,0x0e68 ,0xc18e,0x0e06 ,
+ 0xc178,0x0da4 ,0xc163,0x0d41 ,0xc14f,0x0cdf ,
+ 0xc13b,0x0c7c ,0xc128,0x0c1a ,0xc115,0x0bb7 ,
+ 0xc103,0x0b54 ,0xc0f1,0x0af1 ,0xc0e0,0x0a8e ,
+ 0xc0d0,0x0a2b ,0xc0c0,0x09c7 ,0xc0b1,0x0964 ,
+ 0xc0a3,0x0901 ,0xc095,0x089d ,0xc088,0x0839 ,
+ 0xc07b,0x07d6 ,0xc06f,0x0772 ,0xc064,0x070e ,
+ 0xc059,0x06aa ,0xc04f,0x0646 ,0xc045,0x05e2 ,
+ 0xc03c,0x057e ,0xc034,0x051a ,0xc02c,0x04b5 ,
+ 0xc025,0x0451 ,0xc01f,0x03ed ,0xc019,0x0388 ,
+ 0xc014,0x0324 ,0xc00f,0x02c0 ,0xc00b,0x025b ,
+ 0xc008,0x01f7 ,0xc005,0x0192 ,0xc003,0x012e ,
+ 0xc001,0x00c9 ,0xc000,0x0065 };
diff --git a/src/mod/codecs/mod_isac/webrtc_fft_t_rad.c b/src/mod/codecs/mod_isac/webrtc_fft_t_rad.c
new file mode 100644
index 0000000000..13fbd9f53e
--- /dev/null
+++ b/src/mod/codecs/mod_isac/webrtc_fft_t_rad.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+
+/*
+ * This file contains the Q14 radix-2 tables used in ARM9E optimization routines.
+ *
+ */
+
+extern const unsigned short t_Q14S_rad8[2];
+const unsigned short t_Q14S_rad8[2] = { 0x0000,0x2d41 };
+
+//extern const int t_Q30S_rad8[2];
+//const int t_Q30S_rad8[2] = { 0x00000000,0x2d413ccd };
+
+extern const unsigned short t_Q14R_rad8[2];
+const unsigned short t_Q14R_rad8[2] = { 0x2d41,0x2d41 };
+
+//extern const int t_Q30R_rad8[2];
+//const int t_Q30R_rad8[2] = { 0x2d413ccd,0x2d413ccd };
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/README b/src/mod/endpoints/mod_gsmopen/gsmlib/README
index 8279636209..709f78f2ca 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/README
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/README
@@ -2,7 +2,7 @@ For Linux distros without gsmlib (eg: CentOS):
Here are the original (ancient) sources for gsmlib, and the patch made by Ubuntu for modern compilers.
-In the directory gsmlib-1.10-patched-12ubuntu1 are the patched sources, ready for (no need to patch them again):
+In the directory gsmlib-1.10-patched-13ubuntu are the patched sources, ready for (no need to patch them again):
./configure
make
make install
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/copyright b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/copyright
deleted file mode 100644
index b78ded23aa..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/copyright
+++ /dev/null
@@ -1,26 +0,0 @@
-This package was debianized by Mikael Hedin on
-Thu, 14 Dec 2000 01:06:40 +0100.
-
-It was downloaded from http://www.pxh.de/fs/gsmlib/index.html
-
-Upstream Author: Peter Hofmann
-
-Copyright:
-
- This package 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; version 2 dated June, 1991.
-
- This package 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 package; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- MA 02110-1301, USA.
-
-On Debian GNU/Linux systems, the complete text of the GNU General
-Public License can be found in `/usr/share/common-licenses/GPL'.
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.default b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.default
deleted file mode 100644
index fa72d12e81..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.default
+++ /dev/null
@@ -1,13 +0,0 @@
-PHONEDEV=/dev/mobilephone # or /dev/ttyS0 or /dev/ircomm0
-BAUDRATE=9600
-PIN="" # or 1234
-
-SPOOLDIR=/var/spool/sms
-PRIORITIES=3
-
-SMSADMIN=root
-SUBJECT="SMS delivery report:"
-
-SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
-
-function do_accounting { true; } # it's your turn
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/gsmlib-1.10.debmg/debian/gsm-utils.undocumented b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/gsmlib-1.10.debmg/debian/gsm-utils.undocumented
deleted file mode 100644
index 62d096021d..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/gsmlib-1.10.debmg/debian/gsm-utils.undocumented
+++ /dev/null
@@ -1,2 +0,0 @@
-gsmsmsspool.1
-gsmsmsrequeue.8
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmctl.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmctl.vcproj
deleted file mode 100644
index f079939e50..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmctl.vcproj
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.sln b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.sln
deleted file mode 100644
index 1236577fb5..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.sln
+++ /dev/null
@@ -1,92 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmctl", "gsmctl.vcproj", "{54A7F660-F430-4533-8151-63BEFD12232B}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmlib", "gsmlib.vcproj", "{982662D6-47D2-40D6-A873-E970D407BB2B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmpb", "gsmpb.vcproj", "{7E44C592-6CBC-4A35-817E-D6EA48E4AB1B}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmsendsms", "gsmsendsms.vcproj", "{D9879143-D549-4877-AEB2-667BC5D35F32}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmsmsd", "gsmsmsd.vcproj", "{98F03909-E60D-4797-A35F-F0E535FF4A75}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gsmsmsstore", "gsmsmsstore.vcproj", "{A99A0B10-EB66-40FF-A994-B6D6E0D9167F}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgsmlib", "testgsmlib.vcproj", "{33DFBB83-99BD-449D-A486-B4BCE37544C6}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsms", "testsms.vcproj", "{D3147DAC-F5E2-4ED8-B73C-43A96B042698}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testsms2", "testsms2.vcproj", "{AFAD00BB-1A68-4696-A3EA-4CAD26D9E051}"
- ProjectSection(ProjectDependencies) = postProject
- {982662D6-47D2-40D6-A873-E970D407BB2B} = {982662D6-47D2-40D6-A873-E970D407BB2B}
- EndProjectSection
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {54A7F660-F430-4533-8151-63BEFD12232B}.Debug|Win32.ActiveCfg = Debug|Win32
- {54A7F660-F430-4533-8151-63BEFD12232B}.Debug|Win32.Build.0 = Debug|Win32
- {54A7F660-F430-4533-8151-63BEFD12232B}.Release|Win32.ActiveCfg = Release|Win32
- {54A7F660-F430-4533-8151-63BEFD12232B}.Release|Win32.Build.0 = Release|Win32
- {982662D6-47D2-40D6-A873-E970D407BB2B}.Debug|Win32.ActiveCfg = Debug|Win32
- {982662D6-47D2-40D6-A873-E970D407BB2B}.Debug|Win32.Build.0 = Debug|Win32
- {982662D6-47D2-40D6-A873-E970D407BB2B}.Release|Win32.ActiveCfg = Release|Win32
- {982662D6-47D2-40D6-A873-E970D407BB2B}.Release|Win32.Build.0 = Release|Win32
- {7E44C592-6CBC-4A35-817E-D6EA48E4AB1B}.Debug|Win32.ActiveCfg = Debug|Win32
- {7E44C592-6CBC-4A35-817E-D6EA48E4AB1B}.Debug|Win32.Build.0 = Debug|Win32
- {7E44C592-6CBC-4A35-817E-D6EA48E4AB1B}.Release|Win32.ActiveCfg = Release|Win32
- {7E44C592-6CBC-4A35-817E-D6EA48E4AB1B}.Release|Win32.Build.0 = Release|Win32
- {D9879143-D549-4877-AEB2-667BC5D35F32}.Debug|Win32.ActiveCfg = Debug|Win32
- {D9879143-D549-4877-AEB2-667BC5D35F32}.Debug|Win32.Build.0 = Debug|Win32
- {D9879143-D549-4877-AEB2-667BC5D35F32}.Release|Win32.ActiveCfg = Release|Win32
- {D9879143-D549-4877-AEB2-667BC5D35F32}.Release|Win32.Build.0 = Release|Win32
- {98F03909-E60D-4797-A35F-F0E535FF4A75}.Debug|Win32.ActiveCfg = Debug|Win32
- {98F03909-E60D-4797-A35F-F0E535FF4A75}.Debug|Win32.Build.0 = Debug|Win32
- {98F03909-E60D-4797-A35F-F0E535FF4A75}.Release|Win32.ActiveCfg = Release|Win32
- {98F03909-E60D-4797-A35F-F0E535FF4A75}.Release|Win32.Build.0 = Release|Win32
- {A99A0B10-EB66-40FF-A994-B6D6E0D9167F}.Debug|Win32.ActiveCfg = Debug|Win32
- {A99A0B10-EB66-40FF-A994-B6D6E0D9167F}.Debug|Win32.Build.0 = Debug|Win32
- {A99A0B10-EB66-40FF-A994-B6D6E0D9167F}.Release|Win32.ActiveCfg = Release|Win32
- {A99A0B10-EB66-40FF-A994-B6D6E0D9167F}.Release|Win32.Build.0 = Release|Win32
- {33DFBB83-99BD-449D-A486-B4BCE37544C6}.Debug|Win32.ActiveCfg = Debug|Win32
- {33DFBB83-99BD-449D-A486-B4BCE37544C6}.Debug|Win32.Build.0 = Debug|Win32
- {33DFBB83-99BD-449D-A486-B4BCE37544C6}.Release|Win32.ActiveCfg = Release|Win32
- {33DFBB83-99BD-449D-A486-B4BCE37544C6}.Release|Win32.Build.0 = Release|Win32
- {D3147DAC-F5E2-4ED8-B73C-43A96B042698}.Debug|Win32.ActiveCfg = Debug|Win32
- {D3147DAC-F5E2-4ED8-B73C-43A96B042698}.Debug|Win32.Build.0 = Debug|Win32
- {D3147DAC-F5E2-4ED8-B73C-43A96B042698}.Release|Win32.ActiveCfg = Release|Win32
- {D3147DAC-F5E2-4ED8-B73C-43A96B042698}.Release|Win32.Build.0 = Release|Win32
- {AFAD00BB-1A68-4696-A3EA-4CAD26D9E051}.Debug|Win32.ActiveCfg = Debug|Win32
- {AFAD00BB-1A68-4696-A3EA-4CAD26D9E051}.Debug|Win32.Build.0 = Debug|Win32
- {AFAD00BB-1A68-4696-A3EA-4CAD26D9E051}.Release|Win32.ActiveCfg = Release|Win32
- {AFAD00BB-1A68-4696-A3EA-4CAD26D9E051}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.vcproj
deleted file mode 100644
index 7c668458d4..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmlib.vcproj
+++ /dev/null
@@ -1,332 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmpb.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmpb.vcproj
deleted file mode 100644
index 49a608f6c7..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmpb.vcproj
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsendsms.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsendsms.vcproj
deleted file mode 100644
index 04e6531f1e..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsendsms.vcproj
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsd.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsd.vcproj
deleted file mode 100644
index f6c7eb999b..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsd.vcproj
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsstore.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsstore.vcproj
deleted file mode 100644
index de1b20ff1b..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/gsmsmsstore.vcproj
+++ /dev/null
@@ -1,252 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testgsmlib.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testgsmlib.vcproj
deleted file mode 100644
index 766f863d6f..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testgsmlib.vcproj
+++ /dev/null
@@ -1,221 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms.vcproj
deleted file mode 100644
index 54ae74c491..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms.vcproj
+++ /dev/null
@@ -1,222 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms2.vcproj b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms2.vcproj
deleted file mode 100644
index 824eb4971e..0000000000
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/win32/testsms2.vcproj
+++ /dev/null
@@ -1,222 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/ABOUT-NLS b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/ABOUT-NLS
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/ABOUT-NLS
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/ABOUT-NLS
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/AUTHORS b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/AUTHORS
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/AUTHORS
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/AUTHORS
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/COPYING b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/COPYING
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/COPYING
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/COPYING
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/ChangeLog b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/ChangeLog
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/ChangeLog
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/ChangeLog
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/INSTALL b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/INSTALL
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/INSTALL
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/INSTALL
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/Makefile.am b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/Makefile.am
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/Makefile.am
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/Makefile.am
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/Makefile.in b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/Makefile.in
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/Makefile.in
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/Makefile.in
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/NEWS b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/NEWS
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/NEWS
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/NEWS
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/README b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/README
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/README
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/README
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/TODO b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/TODO
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/TODO
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/TODO
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/acconfig.h b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/acconfig.h
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/acconfig.h
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/acconfig.h
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/acinclude.m4 b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/acinclude.m4
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/acinclude.m4
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/acinclude.m4
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/aclocal.m4 b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/aclocal.m4
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/aclocal.m4
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/aclocal.m4
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/Makefile.am b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/Makefile.am
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/Makefile.am
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/Makefile.am
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/Makefile.in b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/Makefile.in
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/Makefile.in
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/Makefile.in
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmctl.cc b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmctl.cc
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmctl.cc
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmctl.cc
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmpb.cc b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmpb.cc
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmpb.cc
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmpb.cc
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsendsms.cc b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsendsms.cc
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsendsms.cc
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsendsms.cc
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsd.cc b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsd.cc
similarity index 99%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsd.cc
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsd.cc
index e436546225..ffb2db0739 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsd.cc
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsd.cc
@@ -40,6 +40,7 @@
#include
#include
#include
+#include
using namespace std;
using namespace gsmlib;
@@ -413,6 +414,9 @@ int main(int argc, char *argv[])
case 's':
spoolDir = optarg;
break;
+ case 'L':
+ enableSyslog = true;
+ break;
case 'S':
sentDir = optarg;
break;
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsstore.cc b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsstore.cc
similarity index 98%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsstore.cc
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsstore.cc
index e164aafebf..2bb50a0c76 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/apps/gsmsmsstore.cc
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/apps/gsmsmsstore.cc
@@ -292,19 +292,14 @@ int main(int argc, char *argv[])
sourceStore = new SortedSMSStore(sourceMeTa->getSMSStore(storeName));
}
- // make sure destination file exists
+ // make sure destination file exists if specified
+ // Use isFile() for its exception-throwing properties, and discard
+ // return value cos we don't care (yet) whether it's a device or a
+ // regular file.
if (destination != "")
- {
- try
- {
- ofstream f(destination.c_str(), ios::out | ios::app | ios::binary);
- }
- catch (exception)
- {
- }
- }
+ isFile(destination);
- // start accessing destination destination store or file
+ // start accessing destination store or file
if (operation == CopyOp || operation == BackupOp || operation == AddOp ||
operation == DeleteOp)
if (destination == "-")
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/configure b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/configure
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/configure
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/configure
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/configure.in b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/configure.in
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/configure.in
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/configure.in
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsm-utils.cron.d b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.cron.d
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsm-utils.cron.d
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.cron.d
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsm-utils.default b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.default
similarity index 81%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsm-utils.default
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.default
index fa72d12e81..8ab73a9530 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsm-utils.default
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.default
@@ -10,4 +10,4 @@ SUBJECT="SMS delivery report:"
SMSPROCESSOR="" # or /usr/bin/gsmsmsprocessor
-function do_accounting { true; } # it's your turn
+do_accounting () { true; } # it's your turn
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.init b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.init
similarity index 87%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.init
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.init
index 9a783b10ea..7bb3ac0cd1 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/gsm-utils.init
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsm-utils.init
@@ -1,4 +1,13 @@
#! /bin/sh
+### BEGIN INIT INFO
+# Provides: gsm-utils
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Start daemon at boot time
+# Description: Enable service provided by daemon.
+### END INIT INFO
#
# /etc/init.d/gsm-utils: Controls the GSM SMS send daemon
#
@@ -27,11 +36,6 @@ test -n "$SMSPROCESSOR" && OPTIONS="$OPTIONS -a $SMSPROCESSOR"
test -n "$SMSUSER" && STARTOPTS="$STARTOPTS --chuid $SMSUSER"
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils # for overwriting OPTIONS
-if [ ! -d /var/run/gsm-utils ]; then
- mkdir /var/run/gsm-utils
- chown gsmsms:gsmsms /var/run/gsm-utils
-fi
-
case "$1" in
start)
echo -n "Starting $DESC: "
@@ -61,10 +65,10 @@ case "$1" in
restart|force-reload)
echo -n "Restarting $DESC: $NAME"
start-stop-daemon --stop --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
- --make-pidfile --background --exec $DAEMON -- $OPTIONS
+ --make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
sleep 5
start-stop-daemon --start --quiet --pidfile /var/run/gsm-utils/$NAME.pid \
- --make-pidfile --background $STARTOPTS --exec $DAEMON -- $OPTIONS
+ --make-pidfile --background --exec $DAEMON -- $OPTIONS
echo "."
;;
*)
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsrequeue b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsrequeue
similarity index 94%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsrequeue
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsrequeue
index 888c6a993f..88b65c15bf 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsrequeue
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsrequeue
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
#
# /usr/bin/gsmsmsrequeue: Re-queues failed SMS
#
@@ -9,7 +9,8 @@ PRIORITIES=3
SMSADMIN=root
SUBJECT="SMS delivery report:"
-function send_notify {
+send_notify()
+{
tmpfile="$SPOOLDIR/tmp/"`basename "$1"`
status="$2"
if mv "$1" "$tmpfile" 2>/dev/null; then
@@ -21,7 +22,10 @@ function send_notify {
rm "$tmpfile"
fi
}
-function do_accounting { true; }
+do_accounting()
+{
+ true;
+}
test -r /etc/default/gsm-utils && . /etc/default/gsm-utils
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsspool b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsspool
similarity index 98%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsspool
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsspool
index 12ffb008e0..75bc1f9b79 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/contrib/gsmsmsspool
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/contrib/gsmsmsspool
@@ -1,4 +1,4 @@
-#! /bin/sh
+#! /bin/bash
#
# /usr/bin/gsmsmsspool: Queues SMS for sending
#
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/changelog b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/changelog
similarity index 71%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/changelog
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/changelog
index a343c93fa5..86bca0b277 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/changelog
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/changelog
@@ -1,12 +1,73 @@
-gsmlib (1.10-12ubuntu1) hardy; urgency=low
+gsmlib (1.10-13) unstable; urgency=low
- * Merge from Debian unstable. Remaining Ubuntu changes:
- - [debian/gsm-utils.postinst, debian/gsm-utils.init]
- Create /var/run/gsm-utils if it does not exist
- - Actually fix the init script (debian #377448)
- - Set Ubuntu maintainer adress.
+ * Ack NMU, Thanks Michael, Christoph & Petter
+ * debian/control add Homepage:
+ * Update debian/copyright; gsm-lib/COPYING actually specifies LGPL:
+ - fixes lintian:copyright-without-copyright-notice
+ * Update manpages fixes lintian:hyphen-used-as-minus-sign
+ * Update debian/gsm-utils.init
+ - fixes lintian:init.d-script-missing-lsb-short-description
+ * Bug fixes from ubuntu
+ - Don't install contrib/gsm-utils.init dh_installinit debian/gsm-utils.init
+ - Create /var/run/gsm-utils
+ * Add case 'L' to apps/gsmsmsd.cc - thks to Andrew Suffield
+ - syslog support does not work (Closes: #346240)
+ * gsm-utils.init really call restart with --stop first
+ - init script calls --start twice (Closes: #377448)
+ * Explictly set /bin/bash: gsmsmsspool & gsmsmsrequeue
+ - bashism in /bin/sh script (Closes: #464981)
+ - gsmsmsrequeue contains bashism or function error (Closes: #459396)
+ * Patch apps/gsmsmsstore.cc - thks Isaac Wilcox
+ - gsmsmsstore device existence check causes problems with RFCOMM
+ devices (Closes: #340179)
+ * Only start gsmsmsd if set in /etc/default/gsm-utils. crontab -> examples
+ - gsmsmsd should be optional / start only if told so in
+ /etc/default/gsm-utils (Closes: #474093)
+ * Apply patch from Stefan Katerkamp & Jacob Nevins
+ - Gsmsendsms fails with SonyEricsson W880 (fix included) (Closes:
+ #413341)
- -- Albin Tonnerre Wed, 12 Dec 2007 00:45:00 +0100
+ -- Mark Purcell Mon, 06 Oct 2008 15:01:49 +1100
+
+gsmlib (1.10-12.5) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Yet another bashism that was later on reported on the old bug report, thus
+ again closes: #464981
+ * Also found a shell related problem in debian/rules and fixed it.
+ * Bumped standard to 3.7.3.
+
+ -- Michael Meskes Mon, 14 Apr 2008 10:48:19 +0200
+
+gsmlib (1.10-12.4) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Argh, somehow I mananged to upload without fixing the bug completely,
+ sorry. Added those missing braces, closes: #464981.
+
+ -- Michael Meskes Wed, 09 Apr 2008 14:46:08 +0200
+
+gsmlib (1.10-12.3) unstable; urgency=high
+
+ * Non-maintainer upload.
+ * Removed bashism in contrib/gsmsmsrequeue (Closes: #464981).
+
+ -- Michael Meskes Sun, 06 Apr 2008 15:37:35 +0200
+
+gsmlib (1.10-12.2) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Fix FTBFS with GCC 4.3: 'strerror' was not declared in this scope, thanks
+ to Cyril Brulebois for the patch (Closes: #455402).
+
+ -- Christoph Berg Fri, 04 Apr 2008 18:01:05 +0200
+
+gsmlib (1.10-12.1) unstable; urgency=low
+
+ * Non-maintainer upload to solve release goal.
+ * Add LSB dependency header to init.d scripts (Closes: #464061).
+
+ -- Petter Reinholdtsen Fri, 28 Mar 2008 11:39:20 +0100
gsmlib (1.10-12) unstable; urgency=low
@@ -42,27 +103,6 @@ gsmlib (1.10-11) unstable; urgency=low
-- Mark Purcell Sat, 29 Sep 2007 18:22:56 +0100
-gsmlib (1.10-10ubuntu3) feisty; urgency=low
-
- * Rebuild for ldbl128 change (powerpc, sparc).
- * Set Ubuntu maintainer address.
-
- -- Matthias Klose Thu, 1 Mar 2007 22:37:57 +0000
-
-gsmlib (1.10-10ubuntu2) edgy; urgency=low
-
- * [debian/gsm-utils.postinst, debian/gsm-utils.init]
- Create /var/run/gsm-utils if it does not exist
-
- -- Matt Zimmerman Tue, 11 Jul 2006 13:59:12 -0700
-
-gsmlib (1.10-10ubuntu1) edgy; urgency=low
-
- * Re-sync with Debian
- * debian/gsm-utils.init reload/restart was not calling --stop
-
- -- Barry deFreese Sat, 8 Jul 2006 22:52:23 -0400
-
gsmlib (1.10-10) unstable; urgency=low
* FTBFS with G++ 4.1: extra qualifications (Closes: #356109)
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/compat b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/compat
similarity index 100%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/compat
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/compat
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/control b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/control
similarity index 83%
rename from src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/control
rename to src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/control
index 8ae52158a3..b230b8b838 100644
--- a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-12ubuntu1/debian/control
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/control
@@ -1,10 +1,10 @@
Source: gsmlib
Section: comm
Priority: extra
-Maintainer: Ubuntu MOTU Developers
-XSBC-Original-Maintainer: Mark Purcell
+Maintainer: Mark Purcell
Build-Depends: debhelper (>= 3.0.0), chrpath
-Standards-Version: 3.2.1
+Standards-Version: 3.7.3
+Homepage: http://www.pxh.de/fs/gsmlib/
Package: libgsmme-dev
Section: libdevel
@@ -16,8 +16,6 @@ Description: Header files and static libraries for gsmlib
.
gsmlib is a library for access to a GSM mobile phone using the
standards ETSI GSM 07.07, ETSI GSM 07.05, and others.
- .
- Website: http://www.pxh.de/fs/gsmlib/
Package: libgsmme1c2a
Conflicts: libgsmme1, libgsmme1c102, libgsmme1c2
@@ -35,8 +33,6 @@ Description: GSM mobile phone access library
* sending and reception of SMS messages
.
gsmlib uses standard ETSI GSM 07.07, ETSI GSM 07.05, and others.
- .
- Website: http://www.pxh.de/fs/gsmlib/
Package: gsm-utils
Section: comm
@@ -47,6 +43,3 @@ Description: GSM mobile phone access applications
GSM modem or IrDA. Functions include: modification of phone books and
reading, writing, sending and receiving SMS messages. Uses the GSM
standards ETSI GSM 07.07, ETSI GSM 07.05, and others.
- .
- Website: http://www.pxh.de/fs/gsmlib/
-
diff --git a/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/copyright b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/copyright
new file mode 100644
index 0000000000..dcb44c32cd
--- /dev/null
+++ b/src/mod/endpoints/mod_gsmopen/gsmlib/gsmlib-1.10-patched-13ubuntu/debian/copyright
@@ -0,0 +1,34 @@
+This package was debianized by Mikael Hedin on
+Thu, 14 Dec 2000 01:06:40 +0100.
+
+It was downloaded from http://www.pxh.de/fs/gsmlib/index.html
+
+Upstream Author: Peter Hofmann
+
+ext/gsmsiexfer.cc:// * Author: Christian W. Zuckschwerdt
+
+Copyright:
+
+ Copyright (C) 1999-2002 Peter Hofmann
+
+License:
+
+ This package is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This package 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU Lesser General
+Public License can be found in `/usr/share/common-licenses/LGPL'.
+
+The Debian packaging is (C) 2000, Mikael Hedin