Skip to content

Commit 6182715

Browse files
authored
[ogg_opus_player] Ogg opus player on android (#163)
* support ogg_player on Android * add x86_64 libs * rename shared library name * support audio recorder * update pubspec * upgrade lint version
1 parent 14752df commit 6182715

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+5370
-80
lines changed

packages/ogg_opus_player/.metadata

+18-6
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,32 @@
44
# This file should be version controlled.
55

66
version:
7-
revision: 2015143fbf80a1fefd3a222f1d6a264b4d68003d
8-
channel: master
7+
revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
8+
channel: stable
99

1010
project_type: plugin_ffi
1111

1212
# Tracks metadata for the flutter migrate command
1313
migration:
1414
platforms:
1515
- platform: root
16-
create_revision: 2015143fbf80a1fefd3a222f1d6a264b4d68003d
17-
base_revision: 2015143fbf80a1fefd3a222f1d6a264b4d68003d
16+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
17+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
18+
- platform: android
19+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
20+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
21+
- platform: ios
22+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
23+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
1824
- platform: linux
19-
create_revision: 2015143fbf80a1fefd3a222f1d6a264b4d68003d
20-
base_revision: 2015143fbf80a1fefd3a222f1d6a264b4d68003d
25+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
26+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
27+
- platform: macos
28+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
29+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
30+
- platform: windows
31+
create_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
32+
base_revision: 52b3dc25f6471c27b2144594abb11c741cb88f57
2133

2234
# User provided section
2335

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.iml
2+
.gradle
3+
/local.properties
4+
/.idea/workspace.xml
5+
/.idea/libraries
6+
.DS_Store
7+
/build
8+
/captures
9+
.cxx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// The Android Gradle Plugin builds the native code with the Android NDK.
2+
3+
group 'one.mixin.ogg_opus_player'
4+
version '1.0'
5+
6+
buildscript {
7+
8+
ext.kotlin_version = '1.6.10'
9+
ext.exoplayerVersion = '2.18.1'
10+
11+
repositories {
12+
google()
13+
mavenCentral()
14+
}
15+
16+
dependencies {
17+
classpath 'com.android.tools.build:gradle:7.1.2'
18+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
19+
}
20+
}
21+
22+
rootProject.allprojects {
23+
repositories {
24+
google()
25+
mavenCentral()
26+
}
27+
}
28+
29+
apply plugin: 'com.android.library'
30+
apply plugin: 'kotlin-android'
31+
32+
android {
33+
// Bumping the plugin compileSdkVersion requires all clients of this plugin
34+
// to bump the version in their app.
35+
compileSdkVersion 31
36+
37+
// Bumping the plugin ndkVersion requires all clients of this plugin to bump
38+
// the version in their app and to download a newer version of the NDK.
39+
ndkVersion "21.1.6352462"
40+
41+
// Invoke the shared CMake build with the Android Gradle Plugin.
42+
externalNativeBuild {
43+
cmake {
44+
path "./src/main/cpp/CMakeLists.txt"
45+
46+
// The default CMake version for the Android Gradle Plugin is 3.10.2.
47+
// https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
48+
//
49+
// The Flutter tooling requires that developers have CMake 3.10 or later
50+
// installed. You should not increase this version, as doing so will cause
51+
// the plugin to fail to compile for some customers of the plugin.
52+
// version "3.10.2"
53+
}
54+
}
55+
56+
compileOptions {
57+
sourceCompatibility JavaVersion.VERSION_1_8
58+
targetCompatibility JavaVersion.VERSION_1_8
59+
}
60+
61+
kotlinOptions {
62+
jvmTarget = '1.8'
63+
}
64+
65+
sourceSets {
66+
main.java.srcDirs += 'src/main/kotlin'
67+
}
68+
69+
defaultConfig {
70+
minSdkVersion 21
71+
}
72+
}
73+
74+
dependencies {
75+
implementation "com.google.android.exoplayer:exoplayer-core:${exoplayerVersion}"
76+
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'ogg_opus_player'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="one.mixin.oggOpusPlayer">
3+
4+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
5+
6+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
cmake_minimum_required(VERSION 3.4.1)
2+
set(CMAKE_CXX_STANDARD 14)
3+
4+
set(distribution_OPUS_DIR ${CMAKE_SOURCE_DIR}/opus)
5+
6+
add_library(lib_opus STATIC IMPORTED)
7+
set_target_properties(lib_opus PROPERTIES IMPORTED_LOCATION
8+
${distribution_OPUS_DIR}/lib/${ANDROID_ABI}/libopus.a)
9+
10+
add_library(lib_ogg STATIC IMPORTED)
11+
set_target_properties(lib_ogg PROPERTIES IMPORTED_LOCATION
12+
${distribution_OPUS_DIR}/lib/${ANDROID_ABI}/libogg.a)
13+
14+
add_library(lib_opusenc STATIC IMPORTED)
15+
set_target_properties(lib_opusenc PROPERTIES IMPORTED_LOCATION
16+
${distribution_OPUS_DIR}/lib/${ANDROID_ABI}/libopusenc.a)
17+
18+
add_library(ogg_opus_player_plugin SHARED
19+
audio.c)
20+
21+
target_include_directories(ogg_opus_player_plugin PRIVATE
22+
${distribution_OPUS_DIR}/include)
23+
24+
target_link_libraries(ogg_opus_player_plugin
25+
android
26+
lib_opusenc
27+
lib_opus
28+
lib_ogg
29+
log)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#include <jni.h>
2+
#include <stdio.h>
3+
#include <opus.h>
4+
#include <opusenc.h>
5+
#include <stdlib.h>
6+
#include <string.h>
7+
#include "utils.h"
8+
9+
OggOpusEnc *enc;
10+
OggOpusComments *comments;
11+
int error;
12+
13+
static inline void set_bits(uint8_t *bytes, int32_t bitOffset, int32_t value) {
14+
bytes += bitOffset / 8;
15+
bitOffset %= 8;
16+
*((int32_t *) bytes) |= (value << bitOffset);
17+
}
18+
19+
JNIEXPORT jint JNICALL Java_one_mixin_oggOpusPlayer_OpusAudioRecorder_startRecord(JNIEnv *env, jclass clazz, jstring path) {
20+
const char *pathStr = (*env)->GetStringUTFChars(env, path, 0);
21+
if (!pathStr) {
22+
LOGE("Error path");
23+
return 0;
24+
}
25+
comments = ope_comments_create();
26+
enc = ope_encoder_create_file(pathStr, comments, 16000, 1, 0, &error);
27+
if (error != OPE_OK) {
28+
LOGE("Create OggOpusEnc failed");
29+
return error;
30+
}
31+
error = ope_encoder_ctl(enc, OPUS_SET_BITRATE_REQUEST, 16 * 1024);
32+
if (error != OPE_OK) {
33+
return error;
34+
}
35+
36+
return OPE_OK;
37+
}
38+
39+
JNIEXPORT jint JNICALL Java_one_mixin_oggOpusPlayer_OpusAudioRecorder_writeFrame(JNIEnv *env, jclass clazz, jshortArray frame, jint len) {
40+
jshort *sampleBuffer = (*env) -> GetShortArrayElements(env, frame, 0);
41+
int result = ope_encoder_write(enc, sampleBuffer, len);
42+
(*env)->ReleaseShortArrayElements(env, frame, sampleBuffer, 0);
43+
return result;
44+
}
45+
46+
JNIEXPORT void JNICALL Java_one_mixin_oggOpusPlayer_OpusAudioRecorder_stopRecord(JNIEnv *env, jclass clazz) {
47+
ope_encoder_drain(enc);
48+
ope_encoder_destroy(enc);
49+
ope_comments_destroy(comments);
50+
LOGI("ope encoder destroy");
51+
}
52+
53+
JNIEXPORT jbyteArray JNICALL Java_one_mixin_oggOpusPlayer_OpusAudioRecorder_getWaveform2(JNIEnv *env, jclass clazz, jshortArray array, jint length) {
54+
jshort *sampleBuffer = (*env)->GetShortArrayElements(env, array, 0);
55+
const int32_t resultSamples = 100;
56+
uint16_t *samples = malloc(100 * 2);
57+
uint64_t sampleIndex = 0;
58+
uint16_t peakSample = 0;
59+
int32_t sampleRate = (int32_t) max(1, length / resultSamples);
60+
int32_t index = 0;
61+
62+
for (int32_t i = 0; i < length; i++) {
63+
uint16_t sample = (uint16_t) abs(sampleBuffer[i]);
64+
if (sample > peakSample) {
65+
peakSample = sample;
66+
}
67+
if (sampleIndex++ % sampleRate == 0) {
68+
if (index < resultSamples) {
69+
samples[index++] = peakSample;
70+
}
71+
peakSample = 0;
72+
}
73+
}
74+
75+
int64_t sumSamples = 0;
76+
for (int32_t i = 0; i < resultSamples; i++) {
77+
sumSamples += samples[i];
78+
}
79+
uint16_t peak = (uint16_t) (sumSamples * 1.8f / resultSamples);
80+
if (peak < 2500) {
81+
peak = 2500;
82+
}
83+
84+
for (int32_t i = 0; i < resultSamples; i++) {
85+
uint16_t sample = (uint16_t) ((int64_t) samples[i]);
86+
if (sample > peak) {
87+
samples[i] = peak;
88+
}
89+
}
90+
91+
(*env)->ReleaseShortArrayElements(env, array, sampleBuffer, 0);
92+
93+
uint32_t bitStreamLength = resultSamples * 5 / 8 + 1;
94+
jbyteArray result = (*env)->NewByteArray(env, bitStreamLength);
95+
if (result) {
96+
uint8_t *bytes = malloc(bitStreamLength + 4);
97+
memset(bytes, 0, bitStreamLength + 4);
98+
for (int32_t i = 0; i < resultSamples; i++) {
99+
int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak);
100+
set_bits(bytes, i * 5, value & 31);
101+
}
102+
(*env)->SetByteArrayRegion(env, result, 0, bitStreamLength, (jbyte *) bytes);
103+
}
104+
105+
free(samples);
106+
107+
return result;
108+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef __CONFIG_TYPES_H__
2+
#define __CONFIG_TYPES_H__
3+
4+
/* these are filled in by configure */
5+
#define INCLUDE_INTTYPES_H 1
6+
#define INCLUDE_STDINT_H 1
7+
#define INCLUDE_SYS_TYPES_H 1
8+
9+
#if INCLUDE_INTTYPES_H
10+
# include <inttypes.h>
11+
#endif
12+
#if INCLUDE_STDINT_H
13+
# include <stdint.h>
14+
#endif
15+
#if INCLUDE_SYS_TYPES_H
16+
# include <sys/types.h>
17+
#endif
18+
19+
typedef int16_t ogg_int16_t;
20+
typedef uint16_t ogg_uint16_t;
21+
typedef int32_t ogg_int32_t;
22+
typedef uint32_t ogg_uint32_t;
23+
typedef int64_t ogg_int64_t;
24+
25+
#endif

0 commit comments

Comments
 (0)