Commit 1764e70d authored by Daniel Sonck's avatar Daniel Sonck
Browse files

[THFMA-24] Various optimizations and code cleanup

- Removed the unused encoding part from libopus
- Improved the RTP handling
  - Packets are versioned to support protocol upgrades
  - Packets are given to a "listener" instead of relying on external checks to convert to appropriate types
- Solved various warnings and conformity errors
parent ee0fbdab
...@@ -36,10 +36,11 @@ repositories { ...@@ -36,10 +36,11 @@ repositories {
} }
dependencies { 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: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 '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 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'org.java-websocket:Java-WebSocket:1.3.7' implementation 'org.java-websocket:Java-WebSocket:1.3.7'
...@@ -53,6 +54,7 @@ dependencies { ...@@ -53,6 +54,7 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerVersion" implementation "androidx.recyclerview:recyclerview:$rootProject.recyclerVersion"
implementation "androidx.preference:preference:1.1.0" implementation "androidx.preference:preference:1.1.0"
//noinspection GradleDependency
implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion" implementation "androidx.constraintlayout:constraintlayout:$rootProject.constraintLayoutVersion"
implementation "androidx.gridlayout:gridlayout:$rootProject.gridLayoutVersion" implementation "androidx.gridlayout:gridlayout:$rootProject.gridLayoutVersion"
...@@ -119,7 +121,6 @@ android { ...@@ -119,7 +121,6 @@ android {
externalNativeBuild { externalNativeBuild {
cmake { cmake {
version '3.10.2'
path 'src/main/cpp/CMakeLists.txt' path 'src/main/cpp/CMakeLists.txt'
} }
} }
......
...@@ -3,13 +3,20 @@ ...@@ -3,13 +3,20 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="fm.touhou.touhoufm"> 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 <application
android:name=".TouHouFM" android:name=".TouHouFM"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme"
android:fullBackupContent="@xml/backup_descriptor"
android:extractNativeLibs="false">
<activity <activity
android:name=".ui.MainActivity" android:name=".ui.MainActivity"
android:launchMode="singleTop"> android:launchMode="singleTop">
...@@ -59,15 +66,11 @@ ...@@ -59,15 +66,11 @@
<service <service
android:name=".service.MusicService" android:name=".service.MusicService"
android:enabled="true" android:enabled="true"
android:exported="true"> android:exported="false">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" /> <action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter> </intent-filter>
</service> </service>
</application> </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> </manifest>
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# This ensures that a certain set of CMake features is available to # This ensures that a certain set of CMake features is available to
# your build. # your build.
cmake_minimum_required(VERSION 3.10.2) cmake_minimum_required(VERSION 3.15.3)
project(native-opus) project(native-opus)
......
...@@ -5,9 +5,8 @@ add_subdirectory(celt) ...@@ -5,9 +5,8 @@ add_subdirectory(celt)
add_subdirectory(silk) add_subdirectory(silk)
target_sources(${PROJECT_NAME} PUBLIC target_sources(${PROJECT_NAME} PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/opus" "opus"
"${CMAKE_CURRENT_LIST_DIR}/repacketizer" "repacketizer"
"${CMAKE_CURRENT_LIST_DIR}/opus_encoder" "opus_decoder"
"${CMAKE_CURRENT_LIST_DIR}/opus_decoder" "opus_private"
"${CMAKE_CURRENT_LIST_DIR}/opus_private"
) )
\ No newline at end of file
...@@ -2,19 +2,18 @@ target_include_directories(${PROJECT_NAME} PUBLIC ...@@ -2,19 +2,18 @@ target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_CURRENT_LIST_DIR}") "${CMAKE_CURRENT_LIST_DIR}")
target_sources(${PROJECT_NAME} PUBLIC target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_LIST_DIR}/celt celt
${CMAKE_CURRENT_LIST_DIR}/cwrs cwrs
${CMAKE_CURRENT_LIST_DIR}/entcode entcode
${CMAKE_CURRENT_LIST_DIR}/entdec entdec
${CMAKE_CURRENT_LIST_DIR}/entenc kiss_fft
${CMAKE_CURRENT_LIST_DIR}/kiss_fft laplace
${CMAKE_CURRENT_LIST_DIR}/laplace mathops
${CMAKE_CURRENT_LIST_DIR}/mathops mdct
${CMAKE_CURRENT_LIST_DIR}/mdct modes
${CMAKE_CURRENT_LIST_DIR}/modes pitch
${CMAKE_CURRENT_LIST_DIR}/pitch celt_lpc
${CMAKE_CURRENT_LIST_DIR}/celt_lpc quant_bands
${CMAKE_CURRENT_LIST_DIR}/quant_bands rate
${CMAKE_CURRENT_LIST_DIR}/rate vq
${CMAKE_CURRENT_LIST_DIR}/vq bands )
${CMAKE_CURRENT_LIST_DIR}/bands ) \ No newline at end of file
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
...@@ -87,11 +87,6 @@ extern "C" { ...@@ -87,11 +87,6 @@ extern "C" {
#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x) #define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x)
/* Encoder stuff */
int celt_encoder_get_size(int channels);
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels); int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels);
......
...@@ -587,39 +587,6 @@ void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){ ...@@ -587,39 +587,6 @@ void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
} }
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
opus_uint32 i;
celt_assert(_k>0);
#ifndef SMALL_FOOTPRINT
switch(_n){
case 2:{
i=icwrs2(_y,&_k);
ec_enc_uint(_enc,i,ncwrs2(_k));
}break;
case 3:{
i=icwrs3(_y,&_k);
ec_enc_uint(_enc,i,ncwrs3(_k));
}break;
case 4:{
i=icwrs4(_y,&_k);
ec_enc_uint(_enc,i,ncwrs4(_k));
}break;
default:
{
#endif
VARDECL(opus_uint32,u);
opus_uint32 nc;
SAVE_STACK;
ALLOC(u,_k+2U,opus_uint32);
i=icwrs(_n,_k,&nc,_y,u);
ec_enc_uint(_enc,i,nc);
RESTORE_STACK;
#ifndef SMALL_FOOTPRINT
}
break;
}
#endif
}
void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec) void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec)
{ {
......
...@@ -48,48 +48,6 @@ static unsigned ec_laplace_get_freq1(unsigned fs0, int decay) ...@@ -48,48 +48,6 @@ static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
return ft*(opus_int32)(16384-decay)>>15; return ft*(opus_int32)(16384-decay)>>15;
} }
void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
{
unsigned fl;
int val = *value;
fl = 0;
if (val)
{
int s;
int i;
s = -(val<0);
val = (val+s)^s;
fl = fs;
fs = ec_laplace_get_freq1(fs, decay);
/* Search the decaying part of the PDF.*/
for (i=1; fs > 0 && i < val; i++)
{
fs *= 2;
fl += fs+2*LAPLACE_MINP;
fs = (fs*(opus_int32)decay)>>15;
}
/* Everything beyond that has probability LAPLACE_MINP. */
if (!fs)
{
int di;
int ndi_max;
ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
ndi_max = (ndi_max-s)>>1;
di = IMIN(val - i, ndi_max - 1);
fl += (2*di+1+s)*LAPLACE_MINP;
fs = IMIN(LAPLACE_MINP, 32768-fl);
*value = (i+di+s)^s;
}
else
{
fs += LAPLACE_MINP;
fl += fs&~s;
}
celt_assert(fl+fs<=32768);
celt_assert(fs>0);
}
ec_encode_bin(enc, fl, fl+fs, 15);
}
int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay) int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
{ {
......
...@@ -153,271 +153,9 @@ static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBand ...@@ -153,271 +153,9 @@ static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBand
return MIN32(200,SHR32(dist,2*DB_SHIFT-6)); return MIN32(200,SHR32(dist,2*DB_SHIFT-6));
} }
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
const opus_val16 *eBands, opus_val16 *oldEBands,
opus_int32 budget, opus_int32 tell,
const unsigned char *prob_model, opus_val16 *error, ec_enc *enc,
int C, int LM, int intra, opus_val16 max_decay)
{
int i, c;
int badness = 0;
opus_val32 prev[2] = {0,0};
opus_val16 coef;
opus_val16 beta;
if (tell+3 <= budget)
ec_enc_bit_logp(enc, intra, 3);
if (intra)
{
coef = 0;
beta = beta_intra;
} else {
beta = beta_coef[LM];
coef = pred_coef[LM];
}
/* Encode at a fixed coarse resolution */
for (i=start;i<end;i++)
{
c=0;
do {
int bits_left;
int qi, qi0;
opus_val32 q;
opus_val16 x;
opus_val32 f, tmp;
opus_val16 oldE;
opus_val16 decay_bound;
x = eBands[i+c*m->nbEBands];
oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]);
#ifdef FIXED_POINT
f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c];
/* Rounding to nearest integer here is really important! */
qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7);
decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT),
SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay)));
#else
f = x-coef*oldE-prev[c];
/* Rounding to nearest integer here is really important! */
qi = (int)floor(.5f+f);
decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay;
#endif
/* Prevent the energy from going down too quickly (e.g. for bands
that have just one bin) */
if (qi < 0 && x < decay_bound)
{
qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT);
if (qi > 0)
qi = 0;
}
qi0 = qi;
/* If we don't have enough bits to encode all the energy, just assume
something safe. */
tell = ec_tell(enc);
bits_left = budget-tell-3*C*(end-i);
if (i!=start && bits_left < 30)
{
if (bits_left < 24)
qi = IMIN(1, qi);
if (bits_left < 16)
qi = IMAX(-1, qi);
}
if (budget-tell >= 15)
{
int pi;
pi = 2*IMIN(i,20);
ec_laplace_encode(enc, &qi,
prob_model[pi]<<7, prob_model[pi+1]<<6);
}
else if(budget-tell >= 2)
{
qi = IMAX(-1, IMIN(qi, 1));
ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2);
}
else if(budget-tell >= 1)
{
qi = IMIN(0, qi);
ec_enc_bit_logp(enc, -qi, 1);
}
else
qi = -1;
error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT);
badness += abs(qi0-qi);
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7);
#ifdef FIXED_POINT
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp);
#endif
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7);
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
} while (++c < C);
}
return badness;
}
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate)
{
int intra;
opus_val16 max_decay;
VARDECL(opus_val16, oldEBands_intra);
VARDECL(opus_val16, error_intra);
ec_enc enc_start_state;
opus_uint32 tell;
int badness1=0;
opus_int32 intra_bias;
opus_val32 new_distortion;
SAVE_STACK;
intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512));
new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C);
tell = ec_tell(enc);
if (tell+3 > budget)
two_pass = intra = 0;
/* Encode the global flags using a simple probability model
(first symbols in the stream) */
max_decay = QCONST16(16.f,DB_SHIFT);
if (end-start>10)
{
#ifdef FIXED_POINT
max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3));
#else
max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
#endif
}
enc_start_state = *enc;
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16);
ALLOC(error_intra, C*m->nbEBands, opus_val16);
OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
if (two_pass || intra)
{
badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay);
}
if (!intra)
{
unsigned char *intra_buf;
ec_enc enc_intra_state;
opus_int32 tell_intra;
opus_uint32 nstart_bytes;
opus_uint32 nintra_bytes;
int badness2;
VARDECL(unsigned char, intra_bits);
tell_intra = ec_tell_frac(enc);
enc_intra_state = *enc;
nstart_bytes = ec_range_bytes(&enc_start_state);
nintra_bytes = ec_range_bytes(&enc_intra_state);
intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes;
ALLOC(intra_bits, nintra_bytes-nstart_bytes, unsigned char);
/* Copy bits from intra bit-stream */
OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes);
*enc = enc_start_state;
badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay);
if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
{
*enc = enc_intra_state;
/* Copy intra bits to bit-stream */
OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes);
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
OPUS_COPY(error, error_intra, C*m->nbEBands);
intra = 1;
}
} else {
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
OPUS_COPY(error, error_intra, C*m->nbEBands);
}
if (intra)
*delayedIntra = new_distortion;
else
*delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra),
new_distortion);
RESTORE_STACK;
}
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C)
{
int i, c;
/* Encode finer resolution */
for (i=start;i<end;i++)
{
opus_int16 frac = 1<<fine_quant[i];
if (fine_quant[i] <= 0)
continue;
c=0;
do {
int q2;
opus_val16 offset;
#ifdef FIXED_POINT
/* Has to be without rounding */
q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]);
#else
q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac);
#endif
if (q2 > frac-1)
q2 = frac-1;
if (q2<0)
q2 = 0;
ec_enc_bits(enc, q2, fine_quant[i]);
#ifdef FIXED_POINT
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT));
#else
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
#endif
oldEBands[i+c*m->nbEBands] += offset;
error[i+c*m->nbEBands] -= offset;
/*printf ("%f ", error[i] - offset);*/
} while (++c < C);
}
}
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
{
int i, prio, c;
/* Use up the remaining bits */
for (prio=0;prio<2;prio++)
{
for (i=start;i<end && bits_left>=C ;i++)
{
if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
continue;
c=0;
do {
int q2;
opus_val16 offset;
q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
ec_enc_bits(enc, q2, 1);
#ifdef FIXED_POINT
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
#else
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif
oldEBands[i+c*m->nbEBands] += offset;
bits_left--;
} while (++c < C);
}
}
}
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM) void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM)
{ {
......
...@@ -356,10 +356,8 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int ...@@ -356,10 +356,8 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
if (codedBands<=start+2 || band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4) if (codedBands<=start+2 || band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4)
#endif #endif
{ {
ec_enc_bit_logp(ec, 1, 1);
break; break;
} }
ec_enc_bit_logp(ec, 0, 1);
} else if (ec_dec_bit_logp(ec, 1)) { } else if (ec_dec_bit_logp(ec, 1)) {
break; break;
} }
...@@ -390,7 +388,6 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int ...@@ -390,7 +388,6 @@ static inline int interp_bits2pulses(const CELTMode *m, int start, int end, int
if (encode) if (encode)
{ {
*intensity = IMIN(*intensity, codedBands); *intensity = IMIN(*intensity, codedBands);
ec_enc_uint(ec, *intensity-start, codedBands+1-start);