Commit 5d4b7212 authored by Daniel Sonck's avatar Daniel Sonck
Browse files

Merge pull request #42 in THFM/fm.touhou.touhoufm from experimental/kotlin to development

* commit '1764e70d':
  [THFMA-24] Various optimizations and code cleanup
  [THFMA-28][THFMA-27] Implement custom streaming host
parents 6248edd8 1764e70d
......@@ -36,10 +36,11 @@ repositories {
}
dependencies {
testImplementation 'junit:junit:4.12'
testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2'
testImplementation 'org.powermock:powermock:1.6.5'
testImplementation 'org.powermock:powermock-module-junit4:1.6.5'
testImplementation 'org.powermock:powermock-module-junit4:1.7.4'
testImplementation 'org.powermock:powermock-api-mockito:1.6.5'
testImplementation 'io.mockk:mockk:1.8.13.kotlin13'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'org.java-websocket:Java-WebSocket:1.3.7'
......@@ -51,7 +52,9 @@ dependencies {
implementation "androidx.media:media:1.1.0"
implementation "androidx.legacy:legacy-support-v4:$rootProject.legacySupportVersion"
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerVersion"
implementation "androidx.preference:preference:1.1.0"
//noinspection GradleDependency
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "androidx.gridlayout:gridlayout:$rootProject.gridLayoutVersion"
......@@ -118,7 +121,6 @@ android {
externalNativeBuild {
cmake {
version '3.10.2'
path 'src/main/cpp/CMakeLists.txt'
}
}
......
......@@ -3,13 +3,20 @@
xmlns:tools="http://schemas.android.com/tools"
package="fm.touhou.touhoufm">
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".TouHouFM"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
android:fullBackupContent="@xml/backup_descriptor"
android:extractNativeLibs="false">
<activity
android:name=".ui.MainActivity"
android:launchMode="singleTop">
......@@ -59,15 +66,11 @@
<service
android:name=".service.MusicService"
android:enabled="true"
android:exported="true">
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
\ No newline at end of file
......@@ -2,7 +2,7 @@
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.10.2)
cmake_minimum_required(VERSION 3.15.3)
project(native-opus)
......
......@@ -5,9 +5,8 @@ add_subdirectory(celt)
add_subdirectory(silk)
target_sources(${PROJECT_NAME} PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/opus"
"${CMAKE_CURRENT_LIST_DIR}/repacketizer"
"${CMAKE_CURRENT_LIST_DIR}/opus_encoder"
"${CMAKE_CURRENT_LIST_DIR}/opus_decoder"
"${CMAKE_CURRENT_LIST_DIR}/opus_private"
"opus"
"repacketizer"
"opus_decoder"
"opus_private"
)
\ No newline at end of file
......@@ -2,19 +2,18 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_CURRENT_LIST_DIR}")
target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/celt
${CMAKE_CURRENT_LIST_DIR}/cwrs
${CMAKE_CURRENT_LIST_DIR}/entcode
${CMAKE_CURRENT_LIST_DIR}/entdec
${CMAKE_CURRENT_LIST_DIR}/entenc
${CMAKE_CURRENT_LIST_DIR}/kiss_fft
${CMAKE_CURRENT_LIST_DIR}/laplace
${CMAKE_CURRENT_LIST_DIR}/mathops
${CMAKE_CURRENT_LIST_DIR}/mdct
${CMAKE_CURRENT_LIST_DIR}/modes
${CMAKE_CURRENT_LIST_DIR}/pitch
${CMAKE_CURRENT_LIST_DIR}/celt_lpc
${CMAKE_CURRENT_LIST_DIR}/quant_bands
${CMAKE_CURRENT_LIST_DIR}/rate
${CMAKE_CURRENT_LIST_DIR}/vq
${CMAKE_CURRENT_LIST_DIR}/bands )
\ No newline at end of file
celt
cwrs
entcode
entdec
kiss_fft
laplace
mathops
mdct
modes
pitch
celt_lpc
quant_bands
rate
vq
bands )
\ No newline at end of file
......@@ -41,36 +41,33 @@
#include "mathops.h"
#include "rate.h"
opus_uint32 celt_lcg_rand(opus_uint32 seed)
{
return 1664525 * seed + 1013904223;
opus_uint32 celt_lcg_rand(opus_uint32 seed) {
return 1664525 * seed + 1013904223;
}
/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
with this approximation is important because it has an impact on the bit allocation */
static opus_int16 bitexact_cos(opus_int16 x)
{
opus_int32 tmp;
opus_int16 x2;
tmp = (4096+((opus_int32)(x)*(x)))>>13;
celt_assert(tmp<=32767);
x2 = tmp;
x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
celt_assert(x2<=32766);
return 1+x2;
static opus_int16 bitexact_cos(opus_int16 x) {
opus_int32 tmp;
opus_int16 x2;
tmp = (4096 + ((opus_int32) (x) * (x))) >> 13;
celt_assert(tmp <= 32767);
x2 = tmp;
x2 = (32767 - x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
celt_assert(x2 <= 32766);
return 1 + x2;
}
static int bitexact_log2tan(int isin,int icos)
{
int lc;
int ls;
lc=EC_ILOG(icos);
ls=EC_ILOG(isin);
icos<<=15-lc;
isin<<=15-ls;
return (ls-lc)*(1<<11)
+FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
-FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
static int bitexact_log2tan(int isin, int icos) {
int lc;
int ls;
lc = EC_ILOG(icos);
ls = EC_ILOG(isin);
icos <<= 15 - lc;
isin <<= 15 - ls;
return (ls - lc) * (1 << 11)
+ FRAC_MUL16(isin, FRAC_MUL16(isin, -2597) + 7932)
- FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
}
#ifdef FIXED_POINT
......@@ -132,355 +129,341 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
}
#else /* FIXED_POINT */
/* Compute the amplitude (sqrt energy) in each of the bands */
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M*m->shortMdctSize;
c=0; do {
for (i=0;i<end;i++)
{
int j;
opus_val32 sum = 1e-27f;
for (j=M*eBands[i];j<M*eBands[i+1];j++)
sum += X[j+c*N]*X[j+c*N];
bandE[i+c*m->nbEBands] = celt_sqrt(sum);
/*printf ("%f ", bandE[i+c*m->nbEBands]);*/
}
} while (++c<C);
/*printf ("\n");*/
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C,
int M) {
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M * m->shortMdctSize;
c = 0;
do {
for (i = 0; i < end; i++) {
int j;
opus_val32 sum = 1e-27f;
for (j = M * eBands[i]; j < M * eBands[i + 1]; j++)
sum += X[j + c * N] * X[j + c * N];
bandE[i + c * m->nbEBands] = celt_sqrt(sum);
/*printf ("%f ", bandE[i+c*m->nbEBands]);*/
}
} while (++c < C);
/*printf ("\n");*/
}
/* Normalise each band such that the energy is one. */
void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M*m->shortMdctSize;
c=0; do {
for (i=0;i<end;i++)
{
int j;
opus_val16 g = 1.f/(1e-27f+bandE[i+c*m->nbEBands]);
for (j=M*eBands[i];j<M*eBands[i+1];j++)
X[j+c*N] = freq[j+c*N]*g;
}
} while (++c<C);
void
normalise_bands(const CELTMode *m, const celt_sig *OPUS_RESTRICT freq, celt_norm *OPUS_RESTRICT X,
const celt_ener *bandE, int end, int C, int M) {
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M * m->shortMdctSize;
c = 0;
do {
for (i = 0; i < end; i++) {
int j;
opus_val16 g = 1.f / (1e-27f + bandE[i + c * m->nbEBands]);
for (j = M * eBands[i]; j < M * eBands[i + 1]; j++)
X[j + c * N] = freq[j + c * N] * g;
}
} while (++c < C);
}
#endif /* FIXED_POINT */
/* De-normalise the energy to produce the synthesis from the unit-energy bands */
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, celt_sig * OPUS_RESTRICT freq, const celt_ener *bandE, int end, int C, int M)
{
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M*m->shortMdctSize;
celt_assert2(C<=2, "denormalise_bands() not implemented for >2 channels");
c=0; do {
celt_sig * OPUS_RESTRICT f;
const celt_norm * OPUS_RESTRICT x;
f = freq+c*N;
x = X+c*N;
for (i=0;i<end;i++)
{
int j, band_end;
opus_val32 g = SHR32(bandE[i+c*m->nbEBands],1);
j=M*eBands[i];
band_end = M*eBands[i+1];
do {
*f++ = SHL32(MULT16_32_Q15(*x, g),2);
x++;
} while (++j<band_end);
}
for (i=M*eBands[end];i<N;i++)
*f++ = 0;
} while (++c<C);
void
denormalise_bands(const CELTMode *m, const celt_norm *OPUS_RESTRICT X, celt_sig *OPUS_RESTRICT freq,
const celt_ener *bandE, int end, int C, int M) {
int i, c, N;
const opus_int16 *eBands = m->eBands;
N = M * m->shortMdctSize;
celt_assert2(C <= 2, "denormalise_bands() not implemented for >2 channels");
c = 0;
do {
celt_sig *OPUS_RESTRICT f;
const celt_norm *OPUS_RESTRICT x;
f = freq + c * N;
x = X + c * N;
for (i = 0; i < end; i++) {
int j, band_end;
opus_val32 g = SHR32(bandE[i + c * m->nbEBands], 1);
j = M * eBands[i];
band_end = M * eBands[i + 1];
do {
*f++ = SHL32(MULT16_32_Q15(*x, g), 2);
x++;
} while (++j < band_end);
}
for (i = M * eBands[end]; i < N; i++)
*f++ = 0;
} while (++c < C);
}
/* This prevents energy collapse for transients with multiple short MDCTs */
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
int start, int end, opus_val16 *logE, opus_val16 *prev1logE,
opus_val16 *prev2logE, int *pulses, opus_uint32 seed)
{
int c, i, j, k;
for (i=start;i<end;i++)
{
int N0;
opus_val16 thresh, sqrt_1;
int depth;
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C,
int size,
int start, int end, opus_val16 *logE, opus_val16 *prev1logE,
opus_val16 *prev2logE, int *pulses, opus_uint32 seed) {
int c, i, j, k;
for (i = start; i < end; i++) {
int N0;
opus_val16 thresh, sqrt_1;
int depth;
#ifdef FIXED_POINT
int shift;
opus_val32 thresh32;
int shift;
opus_val32 thresh32;
#endif
N0 = m->eBands[i+1]-m->eBands[i];
/* depth in 1/8 bits */
depth = (1+pulses[i])/((m->eBands[i+1]-m->eBands[i])<<LM);
N0 = m->eBands[i + 1] - m->eBands[i];
/* depth in 1/8 bits */
depth = (1 + pulses[i]) / ((m->eBands[i + 1] - m->eBands[i]) << LM);
#ifdef FIXED_POINT
thresh32 = SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1);
thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,thresh32));
{
opus_val32 t;
t = N0<<LM;
shift = celt_ilog2(t)>>1;
t = SHL32(t, (7-shift)<<1);
sqrt_1 = celt_rsqrt_norm(t);
}
thresh32 = SHR32(celt_exp2(-SHL16(depth, 10-BITRES)),1);
thresh = MULT16_32_Q15(QCONST16(0.5f, 15), MIN32(32767,thresh32));
{
opus_val32 t;
t = N0<<LM;
shift = celt_ilog2(t)>>1;
t = SHL32(t, (7-shift)<<1);
sqrt_1 = celt_rsqrt_norm(t);
}
#else
thresh = .5f*celt_exp2(-.125f*depth);
sqrt_1 = celt_rsqrt(N0<<LM);
thresh = .5f * celt_exp2(-.125f * depth);
sqrt_1 = celt_rsqrt(N0 << LM);
#endif
c=0; do
{
celt_norm *X;
opus_val16 prev1;
opus_val16 prev2;
opus_val32 Ediff;
opus_val16 r;
int renormalize=0;
prev1 = prev1logE[c*m->nbEBands+i];
prev2 = prev2logE[c*m->nbEBands+i];
if (C==1)
{
prev1 = MAX16(prev1,prev1logE[m->nbEBands+i]);
prev2 = MAX16(prev2,prev2logE[m->nbEBands+i]);
}
Ediff = EXTEND32(logE[c*m->nbEBands+i])-EXTEND32(MIN16(prev1,prev2));
Ediff = MAX32(0, Ediff);
c = 0;
do {
celt_norm *X;
opus_val16 prev1;
opus_val16 prev2;
opus_val32 Ediff;
opus_val16 r;
int renormalize = 0;
prev1 = prev1logE[c * m->nbEBands + i];
prev2 = prev2logE[c * m->nbEBands + i];
if (C == 1) {
prev1 = MAX16(prev1, prev1logE[m->nbEBands + i]);
prev2 = MAX16(prev2, prev2logE[m->nbEBands + i]);
}
Ediff = EXTEND32(logE[c * m->nbEBands + i]) - EXTEND32(MIN16(prev1, prev2));
Ediff = MAX32(0, Ediff);
#ifdef FIXED_POINT
if (Ediff < 16384)
{
opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(Ediff)),1);
r = 2*MIN16(16383,r32);
} else {
r = 0;
}
if (LM==3)
r = MULT16_16_Q14(23170, MIN32(23169, r));
r = SHR16(MIN16(thresh, r),1);
r = SHR32(MULT16_16_Q15(sqrt_1, r),shift);
if (Ediff < 16384)
{
opus_val32 r32 = SHR32(celt_exp2(-EXTRACT16(Ediff)),1);
r = 2*MIN16(16383,r32);
} else {
r = 0;
}
if (LM==3)
r = MULT16_16_Q14(23170, MIN32(23169, r));
r = SHR16(MIN16(thresh, r),1);
r = SHR32(MULT16_16_Q15(sqrt_1, r),shift);
#else
/* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
short blocks don't have the same energy as long */
r = 2.f*celt_exp2(-Ediff);
if (LM==3)
r *= 1.41421356f;
r = MIN16(thresh, r);
r = r*sqrt_1;
/* r needs to be multiplied by 2 or 2*sqrt(2) depending on LM because
short blocks don't have the same energy as long */
r = 2.f * celt_exp2(-Ediff);
if (LM == 3)
r *= 1.41421356f;
r = MIN16(thresh, r);
r = r * sqrt_1;
#endif
X = X_+c*size+(m->eBands[i]<<LM);
for (k=0;k<1<<LM;k++)
{
/* Detect collapse */
if (!(collapse_masks[i*C+c]&1<<k))
{
/* Fill with noise */
for (j=0;j<N0;j++)
{
seed = celt_lcg_rand(seed);
X[(j<<LM)+k] = (seed&0x8000 ? r : -r);
}
renormalize = 1;
X = X_ + c * size + (m->eBands[i] << LM);
for (k = 0; k < 1 << LM; k++) {
/* Detect collapse */
if (!(collapse_masks[i * C + c] & 1 << k)) {
/* Fill with noise */
for (j = 0; j < N0; j++) {
seed = celt_lcg_rand(seed);
X[(j << LM) + k] = (seed & 0x8000 ? r : -r);
}
renormalize = 1;
}
}
}
/* We just added some energy, so we need to renormalise */
if (renormalize)
renormalise_vector(X, N0<<LM, Q15ONE);
} while (++c<C);
}
/* We just added some energy, so we need to renormalise */
if (renormalize)
renormalise_vector(X, N0 << LM, Q15ONE);
} while (++c < C);
}
}
static void intensity_stereo(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bandE, int bandID, int N)
{
int i = bandID;
int j;
opus_val16 a1, a2;
opus_val16 left, right;
opus_val16 norm;
static void
intensity_stereo(const CELTMode *m, celt_norm *X, celt_norm *Y, const celt_ener *bandE, int bandID,
int N) {
int i = bandID;
int j;
opus_val16 a1, a2;
opus_val16 left, right;
opus_val16 norm;
#ifdef FIXED_POINT
int shift = celt_zlog2(MAX32(bandE[i], bandE[i+m->nbEBands]))-13;
int shift = celt_zlog2(MAX32(bandE[i], bandE[i+m->nbEBands]))-13;
#endif
left = VSHR32(bandE[i],shift);
right = VSHR32(bandE[i+m->nbEBands],shift);
norm = EPSILON + celt_sqrt(EPSILON+MULT16_16(left,left)+MULT16_16(right,right));
a1 = DIV32_16(SHL32(EXTEND32(left),14),norm);
a2 = DIV32_16(SHL32(EXTEND32(right),14),norm);
for (j=0;j<N;j++)
{
celt_norm r, l;
l = X[j];
r = Y[j];
X[j] = MULT16_16_Q14(a1,l) + MULT16_16_Q14(a2,r);
/* Side is not encoded, no need to calculate */
}
left = VSHR32(bandE[i], shift);
right = VSHR32(bandE[i + m->nbEBands], shift);
norm = EPSILON + celt_sqrt(EPSILON + MULT16_16(left, left) + MULT16_16(right, right));
a1 = DIV32_16(SHL32(EXTEND32(left), 14), norm);
a2 = DIV32_16(SHL32(EXTEND32(right), 14), norm);
for (j = 0; j < N; j++) {
celt_norm r, l;
l = X[j];
r = Y[j];
X[j] = MULT16_16_Q14(a1, l) + MULT16_16_Q14(a2, r);
/* Side is not encoded, no need to calculate */
}
}
static void stereo_split(celt_norm *X, celt_norm *Y, int N)
{
int j;
for (j=0;j<N;j++)
{
celt_norm r, l;
l = MULT16_16_Q15(QCONST16(.70710678f,15), X[j]);
r = MULT16_16_Q15(QCONST16(.70710678f,15), Y[j]);
X[j] = l+r;
Y[j] = r-l;
}
static void stereo_split(celt_norm *X, celt_norm *Y, int N) {
int j;
for (j = 0; j < N; j++) {
celt_norm r, l;
l = MULT16_16_Q15(QCONST16(.70710678f, 15), X[j]);
r = MULT16_16_Q15(QCONST16(.70710678f, 15), Y[j]);
X[j] = l + r;
Y[j] = r - l;
}
}
static void stereo_merge(celt_norm *X, celt_norm *Y, opus_val16 mid, int N)
{
int j;
opus_val32 xp=0, side=0;
opus_val32 El, Er;
opus_val16 mid2;
static void stereo_merge(celt_norm *X, celt_norm *Y, opus_val16 mid, int N) {
int j;
opus_val32 xp = 0, side = 0;
opus_val32 El, Er;
opus_val16 mid2;
#ifdef FIXED_POINT
int kl, kr;
int kl, kr;
#endif
opus_val32 t, lgain, rgain;
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
for (j=0;j<N;j++)
{
xp = MAC16_16(xp, X[j], Y[j]);
side = MAC16_16(side, Y[j], Y[j]);