Skip to content

Commit

Permalink
[Things] 🔧 First impl
Browse files Browse the repository at this point in the history
  • Loading branch information
JonathanMercandalli committed Apr 3, 2018
1 parent ad3721f commit 30156f8
Show file tree
Hide file tree
Showing 41 changed files with 1,389 additions and 43 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,6 @@ build/
obj/

gradle.properties
*.hprof
*.hprof

/lib-oboe

This file was deleted.

This file was deleted.

13 changes: 13 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

buildscript {
ext.kotlin_version = '1.2.31'
ext.kotlin_coroutines_version = '0.22.5'
ext.support_version = '27.1.0'
repositories {
google()
jcenter()
Expand All @@ -25,3 +27,14 @@ allprojects {
task clean(type: Delete) {
delete rootProject.buildDir
}


ext {
appVersionCode = 1_00_00
appVersionName = "1.00.00"

compileSdkVersion = 27
buildToolsVersion = "27.0.3"
targetSdkVersion = 27
minSdkVersion = 17
}
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include ':app'
include ':app', ':things'
1 change: 1 addition & 0 deletions things/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
40 changes: 40 additions & 0 deletions things/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror")

set (OBOE_RELATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../lib-oboe)
get_filename_component(OBOE_DIR
${OBOE_RELATIVE_PATH}
ABSOLUTE)

if ((NOT EXISTS ${OBOE_DIR}) OR
(NOT EXISTS ${OBOE_DIR}/CMakeLists.txt))
execute_process(COMMAND git clone
https://github.com/google/oboe.git
${OBOE_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..)
endif()

add_subdirectory(${OBOE_DIR} ./oboe)
include_directories(${OBOE_DIR}/include)

set (DEBUG_UTILS_PATH "../../debug-utils")
set (DEBUG_UTILS_SOURCES ${DEBUG_UTILS_PATH}/trace.cpp)
include_directories(${DEBUG_UTILS_PATH})

add_library( native-lib
SHARED
src/main/cpp/AudioManager.cpp
src/main/cpp/AudioManager.h
src/main/cpp/logging_macros.h
src/main/cpp/NativeAudioManagerBridge.cpp
src/main/cpp/WavGenerator.cpp
src/main/cpp/WavGenerator.h)

find_library( log-lib
log )

target_link_libraries( native-lib
android
${log-lib}
oboe)
55 changes: 55 additions & 0 deletions things/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion

defaultConfig {
applicationId "com.mercandalli.android.apps.theremin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation "com.android.support:appcompat-v7:$support_version"
implementation "com.android.support:cardview-v7:$support_version"
implementation "com.android.support:design:$support_version"
implementation 'com.google.android.things:androidthings:0.6.1-devpreview'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}

task adbLaunchApp(type: Exec) {
group = "adb"
executable = project.android.getAdbExe().toString()
args = ["shell", "am", "start", "-n", "com.mercandalli.android.apps.theremin/.main.MainActivity"]
// adb shell am start -n com.mercandalli.android.apps.theremin/.main.MainActivity
}

task adbKeyHome(type: Exec) {
group = "adb"
commandLine 'adb', 'shell', 'input keyevent 3'
}
21 changes: 21 additions & 0 deletions things/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
25 changes: 25 additions & 0 deletions things/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mercandalli.android.apps.theremin">

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application
android:name=".main.MainApplication"
android:theme="@style/AppTheme">

<uses-library android:name="com.google.android.things" />

<activity android:name=".main.MainActivity">

<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>

</application>

</manifest>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
98 changes: 98 additions & 0 deletions things/src/main/cpp/AudioManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include <inttypes.h>
#include <cstring>

#include "AudioManager.h"
#include "logging_macros.h"

constexpr int32_t kDefaultChannelCount = 2;

AudioManager::AudioManager() {
mChannelCount = kDefaultChannelCount;
createPlaybackStream();
}

AudioManager::~AudioManager() {
closeOutputStream();
}

void AudioManager::createPlaybackStream() {
oboe::AudioStreamBuilder builder;
setupPlaybackStreamParameters(&builder);
oboe::Result result = builder.openStream(&mPlayStream);
if (result == oboe::Result::OK && mPlayStream != nullptr) {
mFramesPerBurst = mPlayStream->getFramesPerBurst();
int channelCount = mPlayStream->getChannelCount();
if (channelCount != mChannelCount) {
LOGW("Requested %d channels but received %d", mChannelCount, channelCount);
}
mPlayStream->setBufferSizeInFrames(mFramesPerBurst);
mLatencyTuner = std::unique_ptr<oboe::LatencyTuner>(new oboe::LatencyTuner(*mPlayStream));
result = mPlayStream->requestStart();
if (result != oboe::Result::OK) {
LOGE("Error starting stream. %s", oboe::convertToText(result));
}
} else {
LOGE("Failed to create stream. Error: %s", oboe::convertToText(result));
}
}

void AudioManager::setupPlaybackStreamParameters(oboe::AudioStreamBuilder *builder) {
builder->setAudioApi(mAudioApi);
builder->setDeviceId(mPlaybackDeviceId);
builder->setChannelCount(mChannelCount);
builder->setSharingMode(oboe::SharingMode::Exclusive);
builder->setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder->setCallback(this);
}

void AudioManager::closeOutputStream() {
if (mPlayStream != nullptr) {
oboe::Result result = mPlayStream->requestStop();
if (result != oboe::Result::OK) {
LOGE("Error stopping output stream. %s", oboe::convertToText(result));
}

result = mPlayStream->close();
if (result != oboe::Result::OK) {
LOGE("Error closing output stream. %s", oboe::convertToText(result));
}
}
}

oboe::DataCallbackResult
AudioManager::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) {
int32_t bufferSize = audioStream->getBufferSizeInFrames();
if (mBufferSizeSelection == kBufferSizeAutomatic) {
mLatencyTuner->tune();
} else if (bufferSize != (mBufferSizeSelection * mFramesPerBurst)) {
audioStream->setBufferSizeInFrames(mBufferSizeSelection * mFramesPerBurst);
}
int32_t channelCount = audioStream->getChannelCount();
if (audioStream->getFormat() == oboe::AudioFormat::Float) {
for (int i = 0; i < channelCount; ++i) {
wavGenerator->render(static_cast<float *>(audioData) + i, i, channelCount,
numFrames);
}
} else {
for (int i = 0; i < channelCount; ++i) {
wavGenerator->render(static_cast<int16_t *>(audioData) + i, i, channelCount,
numFrames);
}
}
return oboe::DataCallbackResult::Continue;
}

void AudioManager::onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) {
if (error == oboe::Result::ErrorDisconnected) restartStream();
}

void AudioManager::restartStream() {
LOGI("Restarting stream");
if (mRestartingLock.try_lock()) {
closeOutputStream();
createPlaybackStream();
mRestartingLock.unlock();
} else {
LOGW("Restart stream operation already in progress - ignoring this request");
}
}
49 changes: 49 additions & 0 deletions things/src/main/cpp/AudioManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef SAMPLER_AUDIO_MANAGER_H
#define SAMPLER_AUDIO_MANAGER_H

#include <thread>
#include <array>
#include <oboe/Oboe.h>
#include <mutex>
#include "WavGenerator.h"

constexpr int32_t kBufferSizeAutomatic = 0;

class AudioManager : oboe::AudioStreamCallback {

public:
AudioManager();

~AudioManager();

oboe::DataCallbackResult
onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames);

void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error);

inline WavGenerator *getWavGenerator() {
return wavGenerator;
}

private:
oboe::AudioApi mAudioApi = oboe::AudioApi::Unspecified;
int32_t mPlaybackDeviceId = oboe::kUnspecified;
int32_t mChannelCount;
int32_t mFramesPerBurst;
int32_t mBufferSizeSelection = kBufferSizeAutomatic;
oboe::AudioStream *mPlayStream;
std::unique_ptr<oboe::LatencyTuner> mLatencyTuner;
std::mutex mRestartingLock;

WavGenerator *wavGenerator = new WavGenerator();

void createPlaybackStream();

void closeOutputStream();

void restartStream();

void setupPlaybackStreamParameters(oboe::AudioStreamBuilder *builder);
};

#endif // SAMPLER_AUDIO_MANAGER_H
Loading

0 comments on commit 30156f8

Please sign in to comment.