├── .gitignore ├── AudioExamples.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── waggoner │ │ └── com │ │ └── audioexamples │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── waggoner │ │ └── audioexamples │ │ ├── MainActivity.java │ │ ├── basic │ │ ├── AudioTrackBufferCallback.java │ │ ├── BasicExample.java │ │ ├── BasicMixer.java │ │ ├── BasicUi.java │ │ └── Drum.java │ │ ├── core │ │ ├── Channel.java │ │ ├── Effect.java │ │ ├── InputSource.java │ │ ├── Mixer.java │ │ └── OutputSource.java │ │ ├── inputs │ │ ├── AudioRecordInput.java │ │ ├── MediaRecorderInput.java │ │ └── inputCallbacks │ │ │ ├── FileWriterCallback.java │ │ │ ├── InputBufferCallback.java │ │ │ └── WildAndWackyProcessingCallback.java │ │ ├── outputs │ │ ├── AudioTrackSource.java │ │ ├── MediaPlayerSource.java │ │ ├── SoundPoolSource.java │ │ ├── StaticAudioTrackSource.java │ │ └── SuperPoweredSource.java │ │ ├── synth │ │ ├── Ocsillator.java │ │ ├── SamplePlayer.java │ │ ├── SinSynth.java │ │ └── SynthUi.java │ │ ├── ui │ │ └── SimpleUi.java │ │ └── util │ │ ├── AudioUtil.java │ │ ├── FileUtil.java │ │ └── WavInfo.java │ ├── jni │ ├── Android.mk │ ├── Application.mk │ ├── SuperpoweredExample.cpp │ └── SuperpoweredExample.h │ ├── libs │ ├── arm64-v8a │ │ └── libSuperpoweredExample.so │ ├── armeabi-v7a │ │ └── libSuperpoweredExample.so │ └── x86 │ │ └── libSuperpoweredExample.so │ ├── obj │ └── local │ │ ├── arm64-v8a │ │ ├── libSuperpoweredExample.so │ │ ├── libstdc++.a │ │ └── objs │ │ │ └── SuperpoweredExample │ │ │ ├── SuperpoweredExample.o │ │ │ ├── SuperpoweredExample.o.d │ │ │ ├── Users │ │ │ └── nathanielwaggoner │ │ │ │ ├── personal │ │ │ │ └── AudioExamples │ │ │ │ │ └── superpowered │ │ │ │ │ └── Superpowered │ │ │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ │ │ └── programming_utils │ │ │ │ └── tools │ │ │ │ └── Superpowered │ │ │ │ └── Superpowered │ │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ │ └── __ │ │ │ └── __ │ │ │ └── __ │ │ │ └── __ │ │ │ └── superpowered │ │ │ └── Superpowered │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ ├── armeabi-v7a │ │ ├── libSuperpoweredExample.so │ │ ├── libstdc++.a │ │ └── objs │ │ │ └── SuperpoweredExample │ │ │ ├── SuperpoweredExample.o │ │ │ ├── SuperpoweredExample.o.d │ │ │ ├── Users │ │ │ └── nathanielwaggoner │ │ │ │ ├── personal │ │ │ │ └── AudioExamples │ │ │ │ │ └── superpowered │ │ │ │ │ └── Superpowered │ │ │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ │ │ └── programming_utils │ │ │ │ └── tools │ │ │ │ └── Superpowered │ │ │ │ └── Superpowered │ │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ │ └── __ │ │ │ └── __ │ │ │ └── __ │ │ │ └── __ │ │ │ └── superpowered │ │ │ └── Superpowered │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ └── x86 │ │ ├── libSuperpoweredExample.so │ │ ├── libstdc++.a │ │ └── objs │ │ └── SuperpoweredExample │ │ ├── SuperpoweredExample.o │ │ ├── SuperpoweredExample.o.d │ │ ├── Users │ │ └── nathanielwaggoner │ │ │ ├── personal │ │ │ └── AudioExamples │ │ │ │ └── superpowered │ │ │ │ └── Superpowered │ │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ │ └── programming_utils │ │ │ └── tools │ │ │ └── Superpowered │ │ │ └── Superpowered │ │ │ ├── SuperpoweredAndroidAudioIO.o │ │ │ └── SuperpoweredAndroidAudioIO.o.d │ │ └── __ │ │ └── __ │ │ └── __ │ │ └── __ │ │ └── superpowered │ │ └── Superpowered │ │ ├── SuperpoweredAndroidAudioIO.o │ │ └── SuperpoweredAndroidAudioIO.o.d │ └── res │ ├── layout │ ├── activity_main.xml │ └── synth_layout.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── raw │ ├── claves.wav │ └── lycka.mp3 │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── superpowered ├── README.txt ├── Superpowered ├── Superpowered3BandEQ.h ├── SuperpoweredAdvancedAudioPlayer.h ├── SuperpoweredAnalyzer.h ├── SuperpoweredAndroidAudioIO.cpp ├── SuperpoweredAndroidAudioIO.h ├── SuperpoweredAudioBuffers.h ├── SuperpoweredBandpassFilterbank.h ├── SuperpoweredDecoder.h ├── SuperpoweredEcho.h ├── SuperpoweredFFT.h ├── SuperpoweredFX.h ├── SuperpoweredFilter.h ├── SuperpoweredFlanger.h ├── SuperpoweredFrequencyDomain.h ├── SuperpoweredGate.h ├── SuperpoweredIOSAudioOutput.h ├── SuperpoweredIOSAudioOutput.mm ├── SuperpoweredMixer.h ├── SuperpoweredOSXAudioIO.h ├── SuperpoweredOSXAudioIO.mm ├── SuperpoweredRecorder.h ├── SuperpoweredResampler.h ├── SuperpoweredReverb.h ├── SuperpoweredRoll.h ├── SuperpoweredSimple.h ├── SuperpoweredTimeStretching.h ├── SuperpoweredWhoosh.h ├── libSuperpoweredARM.a ├── libSuperpoweredARM64.a ├── libSuperpoweredAudio.a └── libSuperpoweredX86.a ├── SuperpoweredLicenseJune232015+LogosForCredit.pdf └── docs ├── _superpowered3_band_e_q_8h_source.html ├── _superpowered_advanced_audio_player_8h_source.html ├── _superpowered_analyzer_8h_source.html ├── _superpowered_android_audio_i_o_8h_source.html ├── _superpowered_audio_buffers_8h_source.html ├── _superpowered_bandpass_filterbank_8h_source.html ├── _superpowered_decoder_8h_source.html ├── _superpowered_echo_8h_source.html ├── _superpowered_f_f_t_8h.html ├── _superpowered_f_f_t_8h_source.html ├── _superpowered_f_x_8h_source.html ├── _superpowered_filter_8h_source.html ├── _superpowered_flanger_8h_source.html ├── _superpowered_frequency_domain_8h_source.html ├── _superpowered_gate_8h_source.html ├── _superpowered_i_o_s_audio_output_8h_source.html ├── _superpowered_mixer_8h_source.html ├── _superpowered_o_s_x_audio_i_o_8h_source.html ├── _superpowered_recorder_8h_source.html ├── _superpowered_resampler_8h_source.html ├── _superpowered_reverb_8h_source.html ├── _superpowered_roll_8h_source.html ├── _superpowered_simple_8h.html ├── _superpowered_simple_8h_source.html ├── _superpowered_time_stretching_8h_source.html ├── _superpowered_whoosh_8h_source.html ├── annotated.html ├── bc_s.png ├── bdwn.png ├── class_superpowered3_band_e_q-members.html ├── class_superpowered3_band_e_q.html ├── class_superpowered_advanced_audio_player-members.html ├── class_superpowered_advanced_audio_player.html ├── class_superpowered_android_audio_i_o-members.html ├── class_superpowered_android_audio_i_o.html ├── class_superpowered_audiobuffer_pool-members.html ├── class_superpowered_audiobuffer_pool.html ├── class_superpowered_audiopointer_list-members.html ├── class_superpowered_audiopointer_list.html ├── class_superpowered_bandpass_filterbank-members.html ├── class_superpowered_bandpass_filterbank.html ├── class_superpowered_decoder-members.html ├── class_superpowered_decoder.html ├── class_superpowered_echo-members.html ├── class_superpowered_echo.html ├── class_superpowered_f_x-members.html ├── class_superpowered_f_x.html ├── class_superpowered_filter-members.html ├── class_superpowered_filter.html ├── class_superpowered_flanger-members.html ├── class_superpowered_flanger.html ├── class_superpowered_frequency_domain-members.html ├── class_superpowered_frequency_domain.html ├── class_superpowered_gate-members.html ├── class_superpowered_gate.html ├── class_superpowered_i_o_s_audio_output-members.html ├── class_superpowered_mono_mixer-members.html ├── class_superpowered_mono_mixer.html ├── class_superpowered_o_s_x_audio_i_o-members.html ├── class_superpowered_offline_analyzer-members.html ├── class_superpowered_offline_analyzer.html ├── class_superpowered_recorder-members.html ├── class_superpowered_recorder.html ├── class_superpowered_resampler-members.html ├── class_superpowered_resampler.html ├── class_superpowered_reverb-members.html ├── class_superpowered_reverb.html ├── class_superpowered_roll-members.html ├── class_superpowered_roll.html ├── class_superpowered_stereo_mixer-members.html ├── class_superpowered_stereo_mixer.html ├── class_superpowered_time_stretching-members.html ├── class_superpowered_time_stretching.html ├── class_superpowered_whoosh-members.html ├── class_superpowered_whoosh.html ├── classes.html ├── closed.png ├── doxygen.css ├── doxygen.png ├── dynsections.js ├── files.html ├── ftv2blank.png ├── ftv2doc.png ├── ftv2folderclosed.png ├── ftv2folderopen.png ├── ftv2lastnode.png ├── ftv2link.png ├── ftv2mlastnode.png ├── ftv2mnode.png ├── ftv2node.png ├── ftv2plastnode.png ├── ftv2pnode.png ├── ftv2splitbar.png ├── ftv2vertline.png ├── functions.html ├── functions_func.html ├── functions_prop.html ├── globals.html ├── globals_func.html ├── hierarchy.html ├── index.html ├── interface_superpowered_i_o_s_audio_output.html ├── interface_superpowered_o_s_x_audio_i_o.html ├── jquery.js ├── nav_f.png ├── nav_g.png ├── nav_h.png ├── open.png ├── protocol_superpowered_i_o_s_audio_i_o_delegate-p-members.html ├── protocol_superpowered_i_o_s_audio_i_o_delegate-p.html ├── protocol_superpowered_o_s_x_audio_i_o_delegate-p-members.html ├── protocol_superpowered_o_s_x_audio_i_o_delegate-p.html ├── struct_superpowered_android_audio_i_o_internals-members.html ├── struct_superpowered_android_audio_i_o_internals.html ├── struct_superpowered_audiobufferlist_element-members.html ├── struct_superpowered_audiobufferlist_element.html ├── structhls_stream_alternative-members.html ├── structhls_stream_alternative.html ├── structmulti_input_channel_map-members.html ├── structmulti_input_channel_map.html ├── structmulti_output_channel_map-members.html ├── structmulti_output_channel_map.html ├── sync_off.png ├── sync_on.png ├── tab_a.png ├── tab_b.png ├── tab_h.png ├── tab_s.png └── tabs.css /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /AudioExamples.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidAudioExamples 2 | 3 | Goals: 4 | 5 | The goals of this project are pretty simple. I'm going to demonstrate all of the Audio pathway (that I can get implemented in time for this talk...) to demonstrate I/O. I specifically want to highlight the varying performance characteristics of the audio approaches, as well as demonstrating their implemenation difficulty. 6 | 7 | This will include Java and C versions. 8 | 9 | Targets: 10 | 11 | SoundPool 12 | 13 | MediaPLayer 14 | 15 | MediaRecorder 16 | 17 | AudioTrack 18 | 19 | AudioEffect 20 | 21 | SuperPowered - obligatory liscense note: AndroidAudioExamples has been Superpowered! 22 | 23 | OpenSLES 24 | 25 | PD - maybe.... 26 | 27 | App Description: 28 | 29 | I'll be writing a stupid simple mixer with 2-4 channels, with some basic effects plug in capabiltiies. You shouldn't look at this as a model of efficiency or mixing audio, but instead as an opprotunity to use various pathaways simultatneously and experieince their different performance characterists. 30 | 31 | The basic dumb first example is going to be a "drum kit" model, but hopefully I can throw together a flexible enough architecture that I can put a sequencer in there and some other fun examples. 32 | 33 | You'll be able to specify the media path for each channel of Audio. 34 | 35 | To Build: 36 | 37 | You'll need a version of Android Studio with NDK support. Otherwise it should be a simple press play build process. 38 | 39 | What to look at? 40 | 41 | If you're just trying to figure out an I/O issue, have a look at either the inputs or outputs in src/main/java/com.waggoner.audioexamples/ 42 | 43 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "22.0.1" 6 | 7 | 8 | defaultConfig { 9 | applicationId "com.waggoner.audioexamples" 10 | minSdkVersion 16 11 | targetSdkVersion 21 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | 16 | sourceSets.main { 17 | jniLibs.srcDir 'src/main/libs' 18 | jni.srcDirs = [] 19 | } 20 | } 21 | 22 | task ndkBuild(type: Exec) { 23 | commandLine '/Users/nathanielwaggoner/programming_utils/tools/android-ndk-r10d/ndk-build', '-B', '-C', file('src/main/jni').absolutePath 24 | } 25 | 26 | tasks.withType(JavaCompile) { 27 | compileTask -> compileTask.dependsOn ndkBuild 28 | } 29 | 30 | buildTypes { 31 | release { 32 | minifyEnabled false 33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 34 | } 35 | } 36 | } 37 | 38 | dependencies { 39 | compile fileTree(dir: 'libs', include: ['*.jar']) 40 | compile 'com.android.support:appcompat-v7:22.2.0' 41 | compile 'com.android.support:appcompat-v7:21.0.+' 42 | compile 'com.android.support:cardview-v7:21.0.+' 43 | compile 'com.android.support:recyclerview-v7:21.0.+' 44 | } 45 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/nathanielwaggoner/android_sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/waggoner/com/audioexamples/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | 6 | import com.waggoner.audioexamples.basic.BasicExample; 7 | import com.waggoner.audioexamples.synth.SynthUi; 8 | 9 | public class MainActivity extends AppCompatActivity { 10 | 11 | BasicExample drumKit; 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_main); 16 | // FileUtil.setUpFilesDir(this); 17 | // drumKit = new BasicExample(this); 18 | // setContentView(drumKit.createUi(this)); 19 | 20 | SynthUi synthUi = new SynthUi(); 21 | setContentView(synthUi.createUI(this)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/basic/AudioTrackBufferCallback.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.basic; 2 | 3 | import com.waggoner.audioexamples.inputs.inputCallbacks.InputBufferCallback; 4 | import com.waggoner.audioexamples.outputs.AudioTrackSource; 5 | 6 | /** 7 | * Created by nathanielwaggoner on 8/28/15. 8 | */ 9 | public class AudioTrackBufferCallback implements InputBufferCallback { 10 | 11 | AudioTrackSource outputSource; 12 | 13 | 14 | @Override 15 | public void prepare() { 16 | outputSource = new AudioTrackSource(); 17 | outputSource.playAudioFromExternalWriter(); 18 | } 19 | 20 | @Override 21 | public void handleBuffer(short[] buffer) { 22 | outputSource.handleShortArray(buffer); 23 | } 24 | 25 | @Override 26 | public void finish() { 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/basic/BasicExample.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.basic; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by nathanielwaggoner on 8/20/15. 8 | */ 9 | public class BasicExample { 10 | 11 | private BasicMixer drumMixer; 12 | private BasicUi drumKitUi; 13 | 14 | 15 | public BasicExample(Context context) { 16 | 17 | /** 18 | * Set up our drum mixer which handles the sounds 19 | */ 20 | drumMixer = new BasicMixer(BasicMixer.DEFAULT_NUM_CHANNELS,BasicMixer.DEFAULT_NUM_INPUTS); 21 | drumMixer.generateDefaultChannels(context); 22 | 23 | /** 24 | * set up our drum kits ui so that it is pretty 25 | */ 26 | drumKitUi = new BasicUi(); 27 | drumKitUi.setMixer(drumMixer); 28 | } 29 | 30 | public View createUi(Context ctx) { 31 | return drumKitUi.createUI(ctx); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/basic/BasicMixer.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.basic; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | 6 | import com.waggoner.audioexamples.R; 7 | import com.waggoner.audioexamples.core.Channel; 8 | import com.waggoner.audioexamples.core.InputSource; 9 | import com.waggoner.audioexamples.core.Mixer; 10 | import com.waggoner.audioexamples.inputs.AudioRecordInput; 11 | import com.waggoner.audioexamples.inputs.MediaRecorderInput; 12 | import com.waggoner.audioexamples.outputs.AudioTrackSource; 13 | import com.waggoner.audioexamples.outputs.MediaPlayerSource; 14 | import com.waggoner.audioexamples.outputs.SoundPoolSource; 15 | import com.waggoner.audioexamples.outputs.StaticAudioTrackSource; 16 | import com.waggoner.audioexamples.outputs.SuperPoweredSource; 17 | import com.waggoner.audioexamples.util.FileUtil; 18 | 19 | import java.io.File; 20 | 21 | /** 22 | * The first attempt at one of these component based instruements. 23 | * Created by nathanielwaggoner on 8/6/15. 24 | */ 25 | public class BasicMixer implements Mixer { 26 | 27 | public static final int DEFAULT_NUM_CHANNELS = 6; 28 | public static final int DEFAULT_NUM_INPUTS = 3; 29 | /** 30 | * TODO: 31 | *

32 | * Move UI creation into helper class for this.... 33 | */ 34 | public static String TAG = BasicMixer.class.getName(); 35 | Channel[] channels; 36 | InputSource[] inputs; 37 | 38 | public BasicMixer(int numChannel, int numInputs) { 39 | channels = new Channel[numChannel]; 40 | inputs = new InputSource[numInputs]; 41 | } 42 | 43 | public void generateDefaultChannels(Context context) { 44 | setChannel(0, new Drum(new MediaPlayerSource(context, R.raw.claves), null)); 45 | setChannel(1, new Drum(new SoundPoolSource(context, R.raw.claves), null)); 46 | setChannel(2, new Drum(new StaticAudioTrackSource(context, R.raw.claves), null)); 47 | setChannel(3, new Drum(new SuperPoweredSource(context, R.raw.claves), null)); 48 | 49 | AudioTrackSource src = new AudioTrackSource(); 50 | src.setPlaybackFile(BasicUi.getFileToPlay(FileUtil.getRecordingsFile(context))); 51 | setChannel(4, new Drum(src, null)); 52 | 53 | 54 | File f = BasicUi.getFileToPlay(context, MediaRecorderInput.THREE_GP_FILE_DIRECTORY); 55 | if(f!=null) { 56 | Uri uri = Uri.parse(f.getAbsolutePath()); 57 | MediaPlayerSource mediaRecordPlaybackSrc = new MediaPlayerSource(context, uri); 58 | setChannel(5, new Drum(mediaRecordPlaybackSrc, null)); 59 | } else { 60 | 61 | } 62 | 63 | inputs[0] = new AudioRecordInput(FileUtil.generateRecordingsFileName(context,null)); 64 | inputs[1] = new MediaRecorderInput(context); 65 | inputs[2] = new AudioRecordInput(new AudioTrackBufferCallback()); 66 | } 67 | 68 | @Override 69 | public int getNumChannels() { 70 | return channels.length; 71 | } 72 | 73 | @Override 74 | public Channel getChannel(int channel) { 75 | Channel ret = null; 76 | if (itFits(channel)) { 77 | ret = channels[channel]; 78 | } 79 | return ret; 80 | } 81 | 82 | @Override 83 | public void setChannel(int channel_number, Channel channel) { 84 | if (itFits(channel_number)) { 85 | if (channels[channel_number] != null) { 86 | channels[channel_number].destroy(); 87 | } 88 | channels[channel_number] = channel; 89 | } 90 | } 91 | 92 | boolean itFits(int channel_number) { 93 | return channels!=null && channel_number < channels.length && channel_number > -1; 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/basic/Drum.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.basic; 2 | 3 | import android.media.AudioTrack; 4 | import android.media.MediaPlayer; 5 | import android.util.Log; 6 | 7 | import com.waggoner.audioexamples.core.OutputSource; 8 | import com.waggoner.audioexamples.core.Channel; 9 | import com.waggoner.audioexamples.core.Effect; 10 | import com.waggoner.audioexamples.outputs.MediaPlayerSource; 11 | import com.waggoner.audioexamples.outputs.StaticAudioTrackSource; 12 | 13 | /** 14 | * Created by nathanielwaggoner on 8/6/15. 15 | */ 16 | public class Drum implements Channel { 17 | public OutputSource mAudioSource; 18 | MediaPlayer.OnCompletionListener mOnCompletionListener; 19 | AudioTrack.OnPlaybackPositionUpdateListener mOnPlaybackPositioNupdateListener; 20 | 21 | /** 22 | * TODO: 23 | * 24 | * Seek to functionality when play is pressed (seek to beginning) 25 | */ 26 | @Override 27 | public void play() { 28 | mAudioSource.playAudio(); 29 | } 30 | 31 | Effect mEffect; 32 | 33 | public Drum(OutputSource source, Effect effect){ 34 | setAudioSource(source); 35 | setEffect(effect); 36 | }; 37 | @Override 38 | public void setAudioSource(OutputSource audioSource) { 39 | mAudioSource = audioSource; 40 | if(mAudioSource instanceof MediaPlayerSource) { 41 | mOnCompletionListener = new MediaPlayerOnCompletionListener(); 42 | ((MediaPlayerSource) mAudioSource).setOnCompletionListener(mOnCompletionListener); 43 | } else if (mAudioSource instanceof StaticAudioTrackSource) { 44 | Log.e("XappTest","Settong plabakupdate listener"); 45 | StaticAudioTrackSource source = (StaticAudioTrackSource) mAudioSource; 46 | source.setPlaybackPositionUpdateListener(mOnPlaybackPositioNupdateListener); 47 | } 48 | } 49 | 50 | @Override 51 | public void processBuffer(short[] buffer) { 52 | 53 | } 54 | 55 | @Override 56 | public OutputSource getAudioSource() { 57 | return mAudioSource ; 58 | } 59 | 60 | @Override 61 | public void destroy() { 62 | mAudioSource.destroy(); 63 | mEffect.destroy(); 64 | } 65 | 66 | @Override 67 | public void setEffect(Effect effect) { 68 | mEffect = effect; 69 | } 70 | 71 | @Override 72 | public Effect getEffect() { 73 | return mEffect; 74 | } 75 | 76 | private class MediaPlayerOnCompletionListener implements MediaPlayer.OnCompletionListener { 77 | 78 | @Override 79 | public void onCompletion(MediaPlayer mp) { 80 | mp.seekTo(0); 81 | } 82 | } 83 | private class OnPlaybackPositionUpdateListener implements AudioTrack.OnPlaybackPositionUpdateListener { 84 | /** 85 | * Called on the listener to notify it that the previously set marker has been reached 86 | * by the playback head. 87 | */ 88 | @Override 89 | public void onMarkerReached(AudioTrack track){ 90 | Log.e("XappTest", "Marker was reached!"); 91 | if(track.getPlayState()!= AudioTrack.PLAYSTATE_STOPPED){ 92 | track.stop(); 93 | } 94 | track.reloadStaticData(); 95 | track.setPlaybackHeadPosition(0); 96 | }; 97 | 98 | /** 99 | * Called on the listener to periodically notify it that the playback head has reached 100 | * a multiple of the notification period. 101 | */ 102 | @Override 103 | 104 | public void onPeriodicNotification(AudioTrack track){ 105 | 106 | }; 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/core/Channel.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.core; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/6/15. 5 | */ 6 | public interface Channel { 7 | 8 | void setAudioSource(OutputSource audioSource); 9 | OutputSource getAudioSource(); 10 | void processBuffer(short[] buffer); 11 | void setEffect(Effect effect); 12 | Effect getEffect(); 13 | void destroy(); 14 | void play(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/core/Effect.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.core; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/6/15. 5 | */ 6 | public interface Effect { 7 | 8 | void destroy(); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/core/InputSource.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.core; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/18/15. 5 | */ 6 | public interface InputSource { 7 | 8 | /** 9 | * returns true if successfully started input 10 | * @return 11 | */ 12 | boolean startInput(); 13 | 14 | /** 15 | * returns true is succesfully stopped input 16 | * @return 17 | */ 18 | boolean stopInput(); 19 | 20 | boolean isRecording(); 21 | 22 | boolean isPlayingRecording(); 23 | 24 | void playRecording(); 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/core/Mixer.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.core; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/6/15. 5 | */ 6 | public interface Mixer { 7 | 8 | /** 9 | * Get the number of channels this mixer is configured for 10 | * @return 11 | */ 12 | int getNumChannels(); 13 | 14 | /** 15 | * Get the channel at this location in the mixer 16 | * @param channel 17 | * @return 18 | */ 19 | Channel getChannel(int channel); 20 | 21 | /** 22 | * Set the Channel at the ChannelNumber location on the mixer 23 | * @param channel_number 24 | * @param channel 25 | */ 26 | void setChannel(int channel_number, Channel channel); 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/core/OutputSource.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.core; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created by nathanielwaggoner on 8/6/15. 7 | */ 8 | public interface OutputSource { 9 | 10 | /** 11 | * TODO: 12 | * 13 | * Add seekTo 14 | */ 15 | void playAudio(); 16 | void stopAudio(); 17 | void destroy(); 18 | void setPlaybackFile(File f); 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/inputs/MediaRecorderInput.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.inputs; 2 | 3 | import android.content.Context; 4 | import android.media.MediaRecorder; 5 | import android.util.Log; 6 | 7 | import com.waggoner.audioexamples.core.InputSource; 8 | import com.waggoner.audioexamples.util.FileUtil; 9 | 10 | /** 11 | * Created by nathanielwaggoner on 8/27/15. 12 | */ 13 | public class MediaRecorderInput implements InputSource{ 14 | 15 | // we have to manually track this in MediaRecrod 16 | private boolean isRecording = false; 17 | // file formats are kind of limited 18 | public static String THREE_GP_FILE_DIRECTORY ="3gp"; 19 | // the big heavy API for recording 20 | MediaRecorder mRecorder; 21 | Context ctx; 22 | // 23 | public MediaRecorderInput(Context ctx) { 24 | this.ctx = ctx; 25 | } 26 | 27 | @Override 28 | public boolean isRecording() { 29 | return isRecording; 30 | } 31 | 32 | @Override 33 | public boolean startInput() { 34 | isRecording = true; 35 | mRecorder = new MediaRecorder(); 36 | mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 37 | mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 38 | mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); 39 | mRecorder.setOutputFile(FileUtil.generateRecordingsFileName(ctx, MediaRecorderInput.THREE_GP_FILE_DIRECTORY)); 40 | try { 41 | mRecorder.prepare(); 42 | } catch (Exception e) { 43 | Log.e("XappTest", Log.getStackTraceString(e)); 44 | } 45 | 46 | mRecorder.start(); 47 | return true; 48 | } 49 | 50 | @Override 51 | public boolean stopInput() { 52 | mRecorder.stop(); 53 | mRecorder.release(); 54 | mRecorder = null; 55 | isRecording = false; 56 | return true; 57 | } 58 | 59 | @Override 60 | public boolean isPlayingRecording() { 61 | return false; 62 | } 63 | 64 | @Override 65 | public void playRecording() { 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/inputs/inputCallbacks/FileWriterCallback.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.inputs.inputCallbacks; 2 | 3 | import android.util.Log; 4 | 5 | import com.waggoner.audioexamples.util.AudioUtil; 6 | 7 | import java.io.FileNotFoundException; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | 11 | /** 12 | * Created by nathanielwaggoner on 8/18/15. 13 | */ 14 | public class FileWriterCallback implements InputBufferCallback { 15 | public static String TAG = FileWriterCallback.class.getName(); 16 | FileOutputStream fos; 17 | String mFileName; 18 | String fileType = ".pcm"; 19 | 20 | public FileWriterCallback(String fileName) { 21 | mFileName = fileName; 22 | } 23 | 24 | 25 | @Override 26 | public void prepare() { 27 | Log.e("XapPTest","Calling prepare: filename: "+mFileName); 28 | try { 29 | fos = new FileOutputStream(mFileName); 30 | } catch (FileNotFoundException fnfe) { 31 | Log.e("Xapptest",Log.getStackTraceString(fnfe)); 32 | Log.e(TAG, "File Not Found Exception in FileWriterCallback prepare()"); 33 | } 34 | } 35 | 36 | @Override 37 | public void handleBuffer(short[] buffer) { 38 | if (fos == null) { 39 | Log.e(TAG, "fos in FileWriterCallback handleBuffer was null"); 40 | throw new RuntimeException("FOS failed to load, failing to write buffer"); 41 | } 42 | try { 43 | byte bData[] = AudioUtil.short2byte(buffer); 44 | fos.write(bData); 45 | } catch (IOException e) { 46 | Log.e(TAG, "IOException in FileWriterCallback handleBuffer()"); 47 | } 48 | } 49 | 50 | @Override 51 | public void finish() { 52 | try { 53 | fos.close(); 54 | } catch (IOException e) { 55 | Log.e(TAG, "IOException in FileWriterCallback finish()"); 56 | 57 | } 58 | } 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/inputs/inputCallbacks/InputBufferCallback.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.inputs.inputCallbacks; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/18/15. 5 | */ 6 | public interface InputBufferCallback { 7 | 8 | 9 | /** 10 | * Do any preparations required for the callback to be ready for audio buffers 11 | */ 12 | void prepare(); 13 | /** 14 | * Accept the audio buffer which has been filled with sound data 15 | * @param buffer 16 | */ 17 | void handleBuffer(short[] buffer); 18 | 19 | /** 20 | * Do any finishing touches before being cleaned up 21 | */ 22 | void finish(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/inputs/inputCallbacks/WildAndWackyProcessingCallback.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.inputs.inputCallbacks; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/21/15. 5 | * 6 | * TODO: Super simple example of a filter applied to input. Just to show you how this works. 7 | */ 8 | public class WildAndWackyProcessingCallback { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/outputs/AudioTrackSource.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.outputs; 2 | 3 | import android.media.AudioFormat; 4 | import android.media.AudioManager; 5 | import android.media.AudioTrack; 6 | import android.util.Log; 7 | 8 | import com.waggoner.audioexamples.basic.AudioTrackBufferCallback; 9 | import com.waggoner.audioexamples.core.OutputSource; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.IOException; 14 | import java.util.concurrent.atomic.AtomicBoolean; 15 | 16 | /** 17 | * AudioTrack for playing longer files 18 | * Created by nathanielwaggoner on 8/21/15. 19 | */ 20 | public class AudioTrackSource implements OutputSource { 21 | public static String TAG = StaticAudioTrackSource.class.getName(); 22 | public static int BUFFER_SIZE = 512; 23 | public static int SAMPLE_RATE = 16000; 24 | 25 | AudioTrack mAudioTrack; 26 | String filePath; 27 | Thread playbackThread; 28 | AudioTrackBufferCallback brt; 29 | 30 | AtomicBoolean play = new AtomicBoolean(false); 31 | // file sample rate 32 | int sampleRate; 33 | // number of channels in the file 34 | int channelCount; 35 | // the channel configuration contstant to use. Derived from channel count. 36 | int channelConfig; 37 | // long as returned fom MediaExtractor 38 | long duration; 39 | 40 | FileInputStream fis; 41 | 42 | public boolean isPlaybackReady = false; 43 | 44 | public void setBrt(AudioTrackBufferCallback brt) { 45 | this.brt = brt; 46 | } 47 | 48 | public AudioTrackSource() { 49 | mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, 1, AudioFormat.ENCODING_PCM_16BIT, 50 | BUFFER_SIZE, AudioTrack.MODE_STREAM); 51 | } 52 | @Override 53 | public void setPlaybackFile(File file) { 54 | if(file!=null) { 55 | filePath = file.getAbsolutePath(); 56 | } 57 | 58 | } 59 | public void setUpFileStream() { 60 | 61 | try { 62 | fis = new FileInputStream(filePath); 63 | isPlaybackReady = true; 64 | } catch (IOException e) { 65 | Log.e("XapPtest", Log.getStackTraceString(e)); 66 | } 67 | } 68 | 69 | 70 | @Override 71 | public void playAudio() { 72 | resetTrack(); 73 | setUpFileStream(); 74 | 75 | // configure byte[] source 76 | // pollByte[] source 77 | // write out 78 | playbackThread = new Thread(new Runnable() { 79 | @Override 80 | public void run() { 81 | try { 82 | byte[] bytes = new byte[BUFFER_SIZE * 2]; 83 | int n; 84 | while (play.get()&& ((n = fis.read(bytes)) != -1)) { 85 | mAudioTrack.write(bytes, 0, bytes.length); 86 | } 87 | play.set(false); 88 | mAudioTrack.stop(); 89 | } catch (Exception e) { 90 | Log.e("XapPTest", Log.getStackTraceString(e)); 91 | } 92 | } 93 | }); 94 | play.set(true); 95 | mAudioTrack.play(); 96 | playbackThread.start(); 97 | } 98 | 99 | public void playAudioFromExternalWriter(){ 100 | resetTrack(); 101 | play.set(true); 102 | mAudioTrack.play(); 103 | } 104 | 105 | 106 | public void handleShortArray(short[] shorts) { 107 | Log.e("XapPTest","Should be writing sine waves"); 108 | mAudioTrack.write(shorts,0,shorts.length); 109 | } 110 | 111 | public void resetTrack() { 112 | if(play.get()) { 113 | play.set(false); 114 | mAudioTrack.stop(); 115 | if(playbackThread!=null) { 116 | try { 117 | playbackThread.join(); 118 | } catch (InterruptedException ie) { 119 | Log.e("XapPTest", Log.getStackTraceString(ie)); 120 | } 121 | } 122 | } 123 | } 124 | @Override 125 | public void stopAudio() { 126 | resetTrack(); 127 | } 128 | 129 | @Override 130 | public void destroy() { 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/outputs/SoundPoolSource.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.outputs; 2 | 3 | import android.content.Context; 4 | import android.media.AudioManager; 5 | import android.media.SoundPool; 6 | 7 | import com.waggoner.audioexamples.core.OutputSource; 8 | 9 | import java.io.File; 10 | 11 | /** 12 | * 13 | * Sound pools are easier than audio tracks, but faster than MediaPlayers. We like them! 14 | * Created by nathanielwaggoner on 8/7/15. 15 | */ 16 | public class SoundPoolSource implements OutputSource { 17 | 18 | SoundPool sp; 19 | int soundId; 20 | 21 | int maxStreams=1; 22 | int streamType = AudioManager.STREAM_MUSIC; 23 | int sourceQuality = 0; // this doesn't do anything right now 24 | 25 | float leftVolume = 1; // range = 0.0 to 1.0) 26 | float rightVolume = 1; // range = 0.0 to 1.0) 27 | 28 | int priority = 0; // stream priority (0 = lowest priority) 29 | int loop = 0 ; 30 | float rate = 1; // playback rate 31 | /** 32 | * Sound pool from raw resources. 33 | * @param context 34 | * @param rawId 35 | */ 36 | public SoundPoolSource(Context context, int rawId) { 37 | sp = new SoundPool(maxStreams, streamType, sourceQuality); 38 | /** soundId for Later handling of sound pool **/ 39 | 40 | soundId = sp.load(context,rawId, 1); 41 | 42 | } 43 | @Override 44 | public void playAudio() { 45 | sp.play(soundId, 1, 1, 0, 0, 1); 46 | } 47 | 48 | @Override 49 | public void stopAudio() { 50 | sp.stop(soundId); 51 | } 52 | 53 | @Override 54 | public void destroy() { 55 | sp.release(); 56 | } 57 | 58 | @Override 59 | public void setPlaybackFile(File f) { 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/outputs/SuperPoweredSource.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.outputs; 2 | 3 | import android.content.Context; 4 | import android.content.res.AssetFileDescriptor; 5 | import android.media.AudioManager; 6 | import android.os.Build; 7 | import android.util.Log; 8 | 9 | import com.waggoner.audioexamples.core.OutputSource; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Created by nathanielwaggoner on 8/14/15. 16 | */ 17 | public class SuperPoweredSource implements OutputSource { 18 | 19 | boolean playing = false; 20 | 21 | public SuperPoweredSource(Context ctx, int resource) { 22 | String samplerateString = null, buffersizeString = null; 23 | 24 | // very important to tie your buffer sizes and smaple rates tot he device is possible. 25 | if (Build.VERSION.SDK_INT >= 17) { 26 | AudioManager audioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE); 27 | samplerateString = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); 28 | buffersizeString = audioManager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER); 29 | } 30 | // all devices are supposed to support 44100, and 512 is a typically conveniest buffer - neither of these is garunteed to be correct. 31 | if (samplerateString == null) samplerateString = "44100"; 32 | if (buffersizeString == null) buffersizeString = "512"; 33 | 34 | // there's no C api's for hitting raw directly, you have to pass in 35 | AssetFileDescriptor fd0 = ctx.getResources().openRawResourceFd(resource); 36 | 37 | long[] params = { 38 | fd0.getStartOffset(), 39 | fd0.getLength(), 40 | Integer.parseInt(samplerateString), 41 | Integer.parseInt(buffersizeString) 42 | }; 43 | try { 44 | fd0.getParcelFileDescriptor().close(); 45 | } catch (IOException e) { 46 | android.util.Log.d("", "Close error."); 47 | } 48 | 49 | SuperpoweredExample(ctx.getPackageResourcePath(), params); 50 | 51 | } 52 | 53 | 54 | @Override 55 | public void playAudio() { 56 | playing = !playing; 57 | onPlayPause(playing); 58 | } 59 | 60 | @Override 61 | public void stopAudio() { 62 | 63 | } 64 | 65 | @Override 66 | public void destroy() { 67 | 68 | } 69 | 70 | @Override 71 | public void setPlaybackFile(File f) { 72 | 73 | } 74 | 75 | static { 76 | System.loadLibrary("SuperpoweredExample"); 77 | // load relevant source library here. 78 | } 79 | 80 | private native void SuperpoweredExample(String apkPath, long[] offsetAndLength); 81 | 82 | private native void onPlayPause(boolean play); 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/synth/Ocsillator.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.synth; 2 | 3 | /** 4 | * 5 | * Basic Ocsillator taken from //http://www.drdobbs.com/jvm/music-components-in-java-creating-oscill/230500178 6 | * with nescesary modifications for Android 7 | * Created by nathanielwaggoner on 9/18/15. 8 | * 9 | */ 10 | public class Ocsillator { 11 | // Instance data 12 | private WAVESHAPE waveshape; 13 | private long periodSamples; 14 | private long sampleNumber; 15 | public enum WAVESHAPE { 16 | SIN, SQU, SAW 17 | } 18 | 19 | /** 20 | * Basic Oscillator Class Constructor 21 | * 22 | * Default instance has SIN waveshape at 1000 Hz 23 | */ 24 | public Ocsillator() { 25 | 26 | // Set defaults 27 | setOscWaveshape(WAVESHAPE.SIN); 28 | setFrequency(1000.0); 29 | } 30 | /** 31 | * Set waveshape of oscillator 32 | * 33 | * @param waveshape Determines the waveshape of this oscillator 34 | */ 35 | public void setOscWaveshape(WAVESHAPE waveshape) { 36 | 37 | this.waveshape = waveshape; 38 | } 39 | 40 | /** 41 | * Set the frequency of the oscillator in Hz. 42 | * 43 | * @param frequency Frequency in Hz for this oscillator 44 | */ 45 | public void setFrequency(double frequency) { 46 | 47 | periodSamples = (long)(SamplePlayer.SAMPLE_RATE / frequency); 48 | } 49 | 50 | /** 51 | * Return the next sample of the oscillator's waveform 52 | * 53 | * @return Next oscillator sample 54 | */ 55 | protected double getSample() { 56 | 57 | double value; 58 | double x = sampleNumber / (double) periodSamples; 59 | 60 | switch (waveshape) { 61 | 62 | default: 63 | case SIN: 64 | value = Math.sin(2.0 * Math.PI * x); 65 | break; 66 | 67 | case SQU: 68 | if (sampleNumber < (periodSamples / 2)) { 69 | value = 1.0; 70 | } else { 71 | value = -1.0; 72 | } 73 | break; 74 | 75 | case SAW: 76 | value = 2.0 * (x - Math.floor(x + 0.5)); 77 | break; 78 | } 79 | sampleNumber = (sampleNumber + 1) % periodSamples; 80 | return value; 81 | } 82 | 83 | /** 84 | * Get a buffer of oscillator samples 85 | * 86 | * @param buffer Array to fill with samples 87 | * 88 | * @return Count of bytes produced. 89 | */ 90 | public int getSamples(short[] buffer) { 91 | for (int i = 0; i < SamplePlayer.SAMPLES_PER_BUFFER; i++) { 92 | double ds = getSample() * Short.MAX_VALUE; 93 | short ss = (short) Math.round(ds); 94 | buffer[i] = ss; 95 | } 96 | return SamplePlayer.SAMPLES_PER_BUFFER; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/synth/SamplePlayer.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.synth; 2 | 3 | import com.waggoner.audioexamples.outputs.AudioTrackSource; 4 | 5 | /** 6 | * Created by nathanielwaggoner on 9/18/15. 7 | */ 8 | public class SamplePlayer { 9 | 10 | AudioTrackSource mTrackSource; 11 | 12 | Ocsillator ocillator; 13 | public static final int SAMPLES_PER_BUFFER = AudioTrackSource.BUFFER_SIZE; 14 | public static final int SAMPLE_RATE = AudioTrackSource.SAMPLE_RATE; 15 | volatile boolean playing; 16 | public SamplePlayer(){ 17 | mTrackSource = new AudioTrackSource(); 18 | ocillator = new Ocsillator(); 19 | } 20 | 21 | public void stop() { 22 | playing = false; 23 | } 24 | public void play() { 25 | playing = true; 26 | Thread playThread = new Thread(new Runnable() { 27 | @Override 28 | public void run() { 29 | mTrackSource.playAudioFromExternalWriter(); 30 | // this is probably going to be chunky at first... 31 | short[] buffer = new short[SAMPLES_PER_BUFFER]; 32 | while(playing) { 33 | int result = ocillator.getSamples(buffer); 34 | mTrackSource.handleShortArray(buffer); 35 | } 36 | } 37 | }); 38 | playThread.start(); 39 | 40 | } 41 | public void setFrequency(int frequency) { 42 | ocillator.setFrequency(frequency); 43 | } 44 | public void setSin() { 45 | ocillator.setOscWaveshape(Ocsillator.WAVESHAPE.SIN); 46 | } 47 | public void setSaw() { 48 | ocillator.setOscWaveshape(Ocsillator.WAVESHAPE.SAW); 49 | } 50 | 51 | public void setSqu() { 52 | ocillator.setOscWaveshape(Ocsillator.WAVESHAPE.SQU); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/synth/SinSynth.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.synth; 2 | 3 | import android.util.Log; 4 | 5 | import com.waggoner.audioexamples.outputs.AudioTrackSource; 6 | 7 | import java.util.concurrent.atomic.AtomicBoolean; 8 | 9 | /** 10 | * Created by nathanielwaggoner on 9/18/15. 11 | */ 12 | public class SinSynth { 13 | 14 | AudioTrackSource outputSource; 15 | AtomicBoolean playing; 16 | int frequency; 17 | public SinSynth(AudioTrackSource outputSource) { 18 | playing = new AtomicBoolean(false); 19 | this.outputSource = outputSource; 20 | } 21 | public void startGeneratingTone(int frequency) { 22 | outputSource.playAudioFromExternalWriter(); 23 | playing.set(true); 24 | Log.e("XapPTest", "Should be starting to generate"); 25 | 26 | startGenerationThread(frequency); 27 | } 28 | 29 | public void stopGeneratingTone() { 30 | playing.set(false); 31 | outputSource.stopAudio(); 32 | } 33 | 34 | private void startGenerationThread(int freq) { 35 | this.frequency = freq; 36 | Thread generatorThread = new Thread(new Runnable() { 37 | @Override 38 | public void run() { 39 | float increment = (float)(2*Math.PI) * frequency / 44100; // angular increment for each sample 40 | float angle = 0; 41 | float samples[] = new float[1024]; 42 | short[] buffer = new short[1024]; 43 | while (playing.get()) { 44 | for (int i = 0; i < samples.length; i++) { 45 | samples[i] = (float) Math.sin(angle); //the part that makes this a sine wave.... 46 | buffer[i] = (short) (samples[i] * Short.MAX_VALUE); 47 | angle += increment; 48 | } 49 | outputSource.handleShortArray(buffer); 50 | } 51 | } 52 | }); 53 | generatorThread.start(); 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/synth/SynthUi.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.synth; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.SeekBar; 8 | import android.widget.TextView; 9 | 10 | import com.waggoner.audioexamples.R; 11 | import com.waggoner.audioexamples.ui.SimpleUi; 12 | 13 | /** 14 | * Created by nathanielwaggoner on 9/18/15. 15 | */ 16 | public class SynthUi implements SimpleUi { 17 | Context ctx; 18 | SamplePlayer sp; 19 | @Override 20 | public View createUI(Context ctx) { 21 | this.ctx = ctx; 22 | sp = new SamplePlayer(); 23 | View layout = LayoutInflater.from(ctx).inflate(R.layout.synth_layout,null); 24 | Button sin = (Button) layout.findViewById(R.id.sin); 25 | sin.setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | sp.setSin(); 29 | } 30 | }); 31 | Button saw = (Button) layout.findViewById(R.id.saw); 32 | saw.setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | sp.setSaw(); 36 | } 37 | }); 38 | 39 | Button squ = (Button) layout.findViewById(R.id.squ); 40 | squ.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | sp.setSqu(); 44 | } 45 | }); 46 | final TextView frequencyDisplay = (TextView) layout.findViewById(R.id.frequency_display); 47 | frequencyDisplay.setText("0"); 48 | SeekBar seekBar = (SeekBar)layout.findViewById(R.id.frequency); 49 | seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 50 | @Override 51 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 52 | sp.setFrequency(progress); 53 | frequencyDisplay.setText(""+progress); 54 | 55 | } 56 | 57 | @Override 58 | public void onStartTrackingTouch(SeekBar seekBar) { 59 | } 60 | 61 | @Override 62 | public void onStopTrackingTouch(SeekBar seekBar) { 63 | 64 | } 65 | }); 66 | final Button start = (Button) layout.findViewById(R.id.start); 67 | start.setOnClickListener(new View.OnClickListener() { 68 | @Override 69 | public void onClick(View v) { 70 | if(sp.playing) { 71 | sp.stop(); 72 | start.setText("Start"); 73 | } else { 74 | sp.play(); 75 | start.setText("Stop"); 76 | } 77 | } 78 | }); 79 | return layout; 80 | } 81 | 82 | @Override 83 | public void destoryUi() { 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/ui/SimpleUi.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.ui; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | /** 7 | * Created by nathanielwaggoner on 8/20/15. 8 | */ 9 | public interface SimpleUi { 10 | 11 | View createUI(Context ctx); 12 | 13 | void destoryUi(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/util/AudioUtil.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.util; 2 | 3 | /** 4 | * Created by nathanielwaggoner on 8/18/15. 5 | */ 6 | public class AudioUtil { 7 | 8 | 9 | public static byte[] short2byte(short[] sData) { 10 | int shortArrsize = sData.length; 11 | byte[] bytes = new byte[shortArrsize * 2]; 12 | for (int i = 0; i < shortArrsize; i++) { 13 | bytes[i * 2] = (byte) (sData[i] & 0x00FF); 14 | bytes[(i * 2) + 1] = (byte) (sData[i] >> 8); 15 | sData[i] = 0; 16 | } 17 | return bytes; 18 | } 19 | 20 | 21 | public static short[] bytesToShorts(byte[] sData) { 22 | int byteArrSize = sData.length; 23 | short[] shorts = new short[byteArrSize / 2]; 24 | for (int i = 0; i < byteArrSize/2; i++) { 25 | shorts[i] = (short)(((sData[i*2+1]&0xFF)<<8) | (sData[i*2]&0xFF)); 26 | } 27 | return shorts; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.util; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import com.waggoner.audioexamples.inputs.MediaRecorderInput; 7 | 8 | import java.io.File; 9 | 10 | /** 11 | * Created by nathanielwaggoner on 8/20/15. 12 | */ 13 | public class FileUtil { 14 | public static String RECORDINGS_FILE= "recordings"; 15 | 16 | public static void setUpFilesDir(Context ctx) { 17 | File f = getRecordingsFile(ctx); 18 | f.mkdirs(); 19 | makeNewSubDir(f.getAbsolutePath() +File.separator 20 | 21 | + MediaRecorderInput.THREE_GP_FILE_DIRECTORY); 22 | 23 | } 24 | public static String generateRecordingsFileName(Context ctx, String dir) { 25 | String base = ctx.getExternalFilesDir(null)+File.separator+RECORDINGS_FILE+File.separator; 26 | if(dir!=null) { 27 | base+=dir+File.separator+generateFileName();; 28 | } else { 29 | base+= generateFileName(); 30 | } 31 | return base; 32 | } 33 | public static String generateFileName() { 34 | return "recording_"+System.currentTimeMillis(); 35 | } 36 | 37 | public static boolean makeNewSubDir(String name) { 38 | Log.e("Xapptest","Making new file: "+name); 39 | return new File(name).mkdirs(); 40 | } 41 | 42 | public static File getRecordingsFile(Context ctx) { 43 | return new File(ctx.getExternalFilesDir(null)+File.separator+RECORDINGS_FILE+File.separator); 44 | } 45 | public static File getRecordingsFileForSubDir(Context ctx, String subDir) { 46 | return new File(ctx.getExternalFilesDir(null)+File.separator+RECORDINGS_FILE+File.separator+subDir+File.separator); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/waggoner/audioexamples/util/WavInfo.java: -------------------------------------------------------------------------------- 1 | package com.waggoner.audioexamples.util; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | // credit to Radiodef http://stackoverflow.com/questions/19991405/how-can-i-detect-whether-a-wav-file-has-a-44-or-46-byte-header 9 | 10 | /** 11 | * Created by nathanielwaggoner on 8/10/15. 12 | */ 13 | public class WavInfo { 14 | 15 | public static int dataOffset; 16 | public static int dataLength; 17 | public static void parseWave(InputStream in) 18 | throws IOException { 19 | int skipTotal = 0; 20 | boolean shouldUpdateDataLength= false; 21 | try { 22 | dataOffset = 12; 23 | dataLength=0; 24 | byte[] bytes = new byte[4]; 25 | // read first 4 bytes 26 | // should be RIFF descriptor 27 | if (in.read(bytes) < 0) { 28 | return; 29 | } 30 | printDescriptor(bytes); 31 | // first subchunk will always be at byte 12 32 | // there is no other dependable constant 33 | in.skip(8); 34 | for (; ; ) { 35 | // read each chunk descriptor 36 | if (in.read(bytes) < 0) { 37 | break; 38 | } 39 | printDescriptor(bytes); 40 | if(new String(bytes,"US-ASCII").equals("data")) { 41 | dataOffset=dataOffset+skipTotal; 42 | shouldUpdateDataLength = true; 43 | Log.e("AudioTest","DataOffset "+ dataOffset); 44 | } 45 | // read chunk length 46 | if (in.read(bytes) < 0) { 47 | break; 48 | } 49 | // skip the length of this chunk 50 | // next bytes should be another descriptor or EOF 51 | int skipAmt = (bytes[0] & 0xFF) 52 | | (bytes[1] & 0xFF) << 8 53 | | (bytes[2] & 0xFF) << 16 54 | | (bytes[3] & 0xFF) << 24; 55 | skipTotal+= skipAmt; 56 | if(shouldUpdateDataLength) { 57 | dataLength=skipAmt; 58 | shouldUpdateDataLength = false; 59 | Log.e("AudioTest","DataLength: "+dataLength); 60 | } 61 | 62 | in.skip(skipAmt); 63 | } 64 | System.out.println("end of file"); 65 | 66 | } finally { 67 | if (in != null) { 68 | in.close(); 69 | } 70 | } 71 | } 72 | 73 | static void printDescriptor(byte[] bytes) 74 | throws IOException { 75 | Log.e("AudioTest", "found '" + new String(bytes, "US-ASCII") + "' descriptor"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/jni/Android.mk: -------------------------------------------------------------------------------- 1 | ## point make at ourselves 2 | LOCAL_PATH := $(call my-dir) 3 | ## path for the superpowered libraries which we care about 4 | SUPERPOWERED_PATH := ../../../../superpowered/Superpowered 5 | ## clear out the global make file parsing vars (LOCAL_ 6 | include $(CLEAR_VARS) 7 | ## first module we want to declare 8 | LOCAL_MODULE := Superpowered 9 | ## architecture based sources 10 | ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) 11 | LOCAL_SRC_FILES := $(SUPERPOWERED_PATH)/libSuperpoweredARM.a 12 | else 13 | ifeq ($(TARGET_ARCH_ABI),arm64-v8a) 14 | LOCAL_SRC_FILES := $(SUPERPOWERED_PATH)/libSuperpoweredARM64.a 15 | else 16 | LOCAL_SRC_FILES := $(SUPERPOWERED_PATH)/libSuperpoweredX86.a 17 | endif 18 | endif 19 | ## point at a make file for static libraries - does all the stuff we need to bundle this guy in 20 | include $(PREBUILT_STATIC_LIBRARY) 21 | ## clear that global space again 22 | include $(CLEAR_VARS) 23 | ## name for our module that includes our sources 24 | LOCAL_MODULE := SuperpoweredExample 25 | ## declare our source files - these are our cpp/c files 26 | LOCAL_SRC_FILES := \ 27 | SuperpoweredExample.cpp \ 28 | $(SUPERPOWERED_PATH)/SuperpoweredAndroidAudioIO.cpp 29 | LOCAL_C_INCLUDES += $(SUPERPOWERED_PATH) 30 | ## linking the android libraries - note openSLES... 31 | LOCAL_LDLIBS := -llog -landroid -lOpenSLES 32 | ## include the superpowered static library in our final lib 33 | LOCAL_STATIC_LIBRARIES := Superpowered 34 | ## i have no idea 35 | LOCAL_CFLAGS = -O3 36 | ## do the build shared library 37 | include $(BUILD_SHARED_LIBRARY) 38 | -------------------------------------------------------------------------------- /app/src/main/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-16 2 | APP_ABI := arm64-v8a armeabi-v7a x86 3 | NDK_TOOLCHAIN_VERSION := clang 4 | APP_OPTIM := release 5 | -------------------------------------------------------------------------------- /app/src/main/jni/SuperpoweredExample.h: -------------------------------------------------------------------------------- 1 | #ifndef Header_SuperpoweredExample 2 | #define Header_SuperpoweredExample 3 | 4 | #include 5 | #include 6 | 7 | #include "SuperpoweredExample.h" 8 | #include "/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAdvancedAudioPlayer.h" 9 | #include "/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.h" 10 | 11 | #define NUM_BUFFERS 2 12 | #define HEADROOM_DECIBEL 3.0f 13 | static const float headroom = powf(10.0f, -HEADROOM_DECIBEL * 0.025); 14 | static SuperpoweredAdvancedAudioPlayer *playerA; 15 | 16 | class SuperpoweredExample { 17 | public: 18 | 19 | SuperpoweredExample(const char *path, int *params); 20 | ~SuperpoweredExample(); 21 | 22 | bool process(short int *output, unsigned int numberOfSamples); 23 | void onPlayPause(bool play); 24 | 25 | private: 26 | pthread_mutex_t mutex; 27 | SuperpoweredAndroidAudioIO *audioSystem; 28 | float *stereoBuffer; 29 | unsigned char activeFx; 30 | float crossValue, volA, volB; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /app/src/main/libs/arm64-v8a/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/libs/arm64-v8a/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/libs/armeabi-v7a/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/libs/armeabi-v7a/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/libs/x86/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/libs/x86/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/arm64-v8a/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/libstdc++.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/SuperpoweredExample.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/SuperpoweredExample.o -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/arm64-v8a/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/armeabi-v7a/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/libstdc++.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/SuperpoweredExample.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/SuperpoweredExample.o -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/armeabi-v7a/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/libSuperpoweredExample.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/x86/libSuperpoweredExample.so -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/libstdc++.a: -------------------------------------------------------------------------------- 1 | ! 2 | -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/objs/SuperpoweredExample/SuperpoweredExample.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/x86/objs/SuperpoweredExample/SuperpoweredExample.o -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/x86/objs/SuperpoweredExample/Users/nathanielwaggoner/personal/AudioExamples/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/x86/objs/SuperpoweredExample/Users/nathanielwaggoner/programming_utils/tools/Superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/obj/local/x86/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NathanielWaggoner/AndroidAudioExamples/db54315233eb4cfe495a33c3e0a62d6c3ee07564/app/src/main/obj/local/x86/objs/SuperpoweredExample/__/__/__/__/superpowered/Superpowered/SuperpoweredAndroidAudioIO.o -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/synth_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 |