Merge pull request #103 from cnlohr/androidtest

Get closer (but not there) to a working Android version.
This commit is contained in:
CNLohr 2020-05-03 07:15:22 -07:00 committed by GitHub
commit acf2e9c180
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 411 additions and 9 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "embedded8266/esp82xx"]
path = embedded8266/esp82xx
url = https://github.com/cnlohr/esp82xx.git
[submodule "colorchord2/rawdraw"]
path = colorchord2/rawdraw
url = https://github.com/cntools/rawdraw

View file

@ -5,6 +5,7 @@
#include <stdio.h>
#include "parameters.h"
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <string.h>
#include "color.h"

View file

@ -14,10 +14,12 @@ RAWDRAWLIBS:=-lX11 -lm -lpthread -lXinerama -lXext
LDLIBS:=-lpthread -lasound -lm -lpulse-simple -lpulse -ludev -lrt
CFLAGS:=-g -O0 -flto -Wall -ffast-math -I../embeddedcommon -I. -DICACHE_FLASH_ATTR=
CFLAGS:=-g -O1 -flto -Wall -ffast-math -I../embeddedcommon -I. -DICACHE_FLASH_ATTR=
EXTRALIBS:=-lusb-1.0
colorchord : os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o
OBJS:=os_generic.o main.o dft.o decompose.o filter.o color.o notefinder.o util.o outdrivers.o $(RAWDRAW) $(SOUND) $(OUTS) parameters.o chash.o hook.o ../embeddedcommon/DFT32.o configs.o
colorchord : $(OBJS)
gcc -o $@ $^ $(CFLAGS) $(LDLIBS) $(EXTRALIBS) $(RAWDRAWLIBS)
@ -26,4 +28,4 @@ colorchord.exe : os_generic.c main.c dft.c decompose.c filter.c color.c notefin
clean :
rm -rf *.o *~ colorchord colorchord.exe embeddedcc
rm -rf *.o *~ colorchord colorchord.exe embeddedcc $(OBJS)

View file

@ -62,7 +62,50 @@ void SetEnvValues( int force )
if( !hits && !force ) return;
//Otherwise, something changed.
#ifdef ANDROID
SetParametersFromString( "cpu_autolimit=1" );
SetParametersFromString( "set_screenx=720" );
SetParametersFromString( "set_screeny=480" );
SetParametersFromString( "buffer=384" );
SetParametersFromString( "play=0" );
SetParametersFromString( "rec=1" );
SetParametersFromString( "channels=2" );
SetParametersFromString( "samplerate=44100" );
SetParametersFromString( "sourcename=default" );
SetParametersFromString( "amplify=2.0" );
SetParametersFromString( "base_hz=55" );
SetParametersFromString( "dft_iir=0.6" );
SetParametersFromString( "dft_q=20.0000" );
SetParametersFromString( "dft_speedup=1000.0000" );
SetParametersFromString( "octaves=5" );
SetParametersFromString( "do_progressive_dft=4" );
SetParametersFromString( "filter_iter=2" );
SetParametersFromString( "filter_strength=.5" );
SetParametersFromString( "freqbins = 24" );
SetParametersFromString( "do_progressive_dft=4" );
SetParametersFromString( "note_attach_amp_iir=0.3500" );
SetParametersFromString( "note_attach_amp_iir2=0.250" );
SetParametersFromString( "note_combine_distance=0.5000" );
SetParametersFromString( "note_jumpability=1.8000" );
SetParametersFromString( "note_minimum_new_distribution_value=0.0200" );
SetParametersFromString( "note_out_chop=0.05000" );
SetParametersFromString( "outdrivers=OutputVoronoi,DisplayArray" );
SetParametersFromString( "note_attach_amp_iir2=0.250" );
SetParametersFromString( "lightx=64" );
SetParametersFromString( "lighty=32" );
SetParametersFromString( "fromsides=1" );
SetParametersFromString( "shape_cutoff=0.03" );
SetParametersFromString( "satamp=5.000" );
SetParametersFromString( "amppow=2.510" );
SetParametersFromString( "distpow=1.500" );
#else
LoadFile( InitialFile[0] );
for( i = 1; i < gargc; i++ )
@ -78,6 +121,7 @@ void SetEnvValues( int force )
LoadFile( gargv[i] );
}
}
#endif
}
void ProcessArgs()

View file

@ -0,0 +1,36 @@
outdrivers = DisplayArray,DisplayNetwork,OutputCells
#OutputVoronoi
leds = 199
light_siding = 1.0 #Turn this to ~1.9 for more uniformity, ~1.0 for less.
satamp = 1.600
is_loop=0
led_floor = .1 #Turn to .25 for more uniformity, .1 for less.
#note_attach_amp_iir = .3 #.3000
#note_attach_amp_iir2 = .15 #.1500
#note_attach_freq_iir = .3 #0.3000
steady_bright = 0
#dft_iir = 0.0
#dft_q = 20.0000
#dft_speedup = 1000.0000
sourcename = default
# alsa_output.pci-0000_01_00.1.hdmi-stereo.monitor
# alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor
#alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
skipfirst = 0
firstval = 0
port = 7000
address = 192.168.43.179
#address = 192.168.0.245
slope=.10
amplify=.9
headless = 00
zigzag = 0
lightx = 13
lighty = 19
qtyamp = 50
timebased = 1
snakey = 0

View file

@ -18,6 +18,36 @@
#include "hook.h"
#include "configs.h"
#ifdef ANDROID
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <android/log.h>
#include <pthread.h>
static int pfd[2];
static pthread_t loggingThread;
static const char *LOG_TAG = "colorchord";
static void *loggingFunction(void*v) {
ssize_t readSize;
char buf[128];
while((readSize = read(pfd[0], buf, sizeof buf - 1)) > 0) {
if(buf[readSize - 1] == '\n') {
--readSize;
}
buf[readSize] = 0; // add null-terminator
__android_log_write(ANDROID_LOG_DEBUG, LOG_TAG, buf); // Set any log level you want
}
return 0;
}
#endif
struct SoundDriver * sd;
#if defined(WIN32) || defined(USE_WINDOWS)
@ -162,9 +192,40 @@ void SoundCB( float * out, float * in, int samplesr, int * samplesp, struct Soun
*samplesp = samplesr;
}
#ifdef ANDROID
void HandleSuspend()
{
//Unused.
}
void HandleResume()
{
//Unused.
}
#endif
int main(int argc, char ** argv)
{
int i;
#ifdef ANDROID
setvbuf(stdout, 0, _IOLBF, 0); // make stdout line-buffered
setvbuf(stderr, 0, _IONBF, 0); // make stderr unbuffered
/* create the pipe and redirect stdout and stderr */
pipe(pfd);
dup2(pfd[1], 1);
dup2(pfd[1], 2);
/* spawn the logging thread */
if(pthread_create(&loggingThread, 0, loggingFunction, 0) == -1) {
return -1;
}
pthread_detach(loggingThread);
#endif
#ifdef TCC
void ManuallyRegisterDevices();
ManuallyRegisterDevices();
@ -181,6 +242,8 @@ int main(int argc, char ** argv)
WSAStartup(0x202, &wsaData);
strcpy( sound_source, "WIN" );
#elif defined( ANDROID )
strcpy( sound_source, "ANDROID" );
#else
strcpy( sound_source, "PULSE" );
#endif
@ -263,6 +326,7 @@ int main(int argc, char ** argv)
double Last = Now;
while(1)
{
printf( ".\n" );
char stt[1024];
//Handle Rawdraw frame swappign

View file

@ -228,7 +228,12 @@ void OGCancelThread( og_thread_t ot )
{
return;
}
#ifdef ANDROID
void * fakeret;
pthread_join( *(pthread_t*)ot, &fakeret );
#else
pthread_cancel( *(pthread_t*)ot );
#endif
free( ot );
}

View file

@ -1,10 +1,10 @@
This is a vornoi thing:
outdrivers = DisplayArray, OutputProminent
lightx = 2
lighty = 2
leds = 4
fromsides = 1
outdrivers = DisplayArray, OutputCells
lightx = 3
lighty = 3
leds = 9
fromsides = 0
shape_cutoff = 0.03
satamp = 5.000
amppow = 2.510
@ -13,7 +13,8 @@ distpow = 1.500
samplerate = 11025
buffer = 64
sourcename = default
sourcename = alsa_output.pci-0000_00_1f.3.analog-stereo.monitor
#default
amplify = 2.5
note_attach_amp_iir = 0.9000

1
colorchord2/rawdraw Submodule

@ -0,0 +1 @@
Subproject commit e5acb751f337f3ae9e558e98907be8e3d6f8381f

View file

@ -4,6 +4,7 @@
#include "os_generic.h"
#include "parameters.h"
#include <alsa/asoundlib.h>
#include <string.h>
#define BUFFERSETS 4

244
colorchord2/sound_android.c Normal file
View file

@ -0,0 +1,244 @@
//Copyright 2019-2020 <>< Charles Lohr under the ColorChord License.
// This should be used with rawdrawandroid
#include "sound.h"
#include "os_generic.h"
#include <pthread.h> //Using android threads not os_generic threads.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef NO_SOUND_PARAMETERS
#include "parameters.h"
#else
#define GetParameterI( x, y ) (y)
#define GetParameterS( x, y ) (y)
#endif
//based on https://github.com/android/ndk-samples/blob/master/native-audio/app/src/main/cpp/native-audio-jni.c
// for native audio
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <android_native_app_glue.h>
#include <android/log.h>
#include <jni.h>
#include <native_activity.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, APPNAME, __VA_ARGS__))
#define printf( x...) LOGI( x )
#define RECORDER_FRAMES 1024
#define BUFFERSETS 4
#define BLOCKING
//Across all sound systems.
static pthread_mutex_t audioEngineLock = PTHREAD_MUTEX_INITIALIZER;
struct SoundDriverAndroid
{
void (*CloseFn)( struct SoundDriverAndroid * object );
int (*SoundStateFn)( struct SoundDriverAndroid * object );
SoundCBType callback;
SLObjectItf engineObject;
SLEngineItf engineEngine;
SLRecordItf recorderRecord;
SLObjectItf recorderObject;
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
unsigned recorderSize;
short recorderBuffer[RECORDER_FRAMES];
};
void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
{
struct SoundDriverAndroid * r = (struct SoundDriverAndroid*)context;
int samplesp = 0;
float buffout[RECORDER_FRAMES];
int i;
short * rb = r->recorderBuffer;
for( i = 0; i < RECORDER_FRAMES; i++ ) buffout[i] = (rb[i]+0.5)/32767.5;
r->callback( 0, buffout, RECORDER_FRAMES, &samplesp, r );
(*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer));
}
static struct SoundDriverAndroid* InitAndroidSound( struct SoundDriverAndroid * r )
{
SLresult result;
LOGI( "Starting InitAndroidSound\n" );
// create engine
result = slCreateEngine(&r->engineObject, 0, NULL, 0, NULL, NULL);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// realize the engine
result = (*r->engineObject)->Realize(r->engineObject, SL_BOOLEAN_FALSE);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the engine interface, which is needed in order to create other objects
result = (*r->engineObject)->GetInterface(r->engineObject, SL_IID_ENGINE, &r->engineEngine);
assert(SL_RESULT_SUCCESS == result);
(void)result;
///////////////////////////////////////////////////////////////////////////////////////////////////////
// configure audio source
SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
SLDataSource audioSrc = {&loc_dev, NULL};
// configure audio sink
SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm ={
SL_DATAFORMAT_PCM,
1,
SL_SAMPLINGRATE_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_CENTER,
SL_BYTEORDER_LITTLEENDIAN,
};
SLDataSink audioSnk = {&loc_bq, &format_pcm};
// create audio recorder
// (requires the RECORD_AUDIO permission)
const SLInterfaceID id[1] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
const SLboolean req[1] = {SL_BOOLEAN_TRUE};
result = (*r->engineEngine)->CreateAudioRecorder(r->engineEngine, &r->recorderObject, &audioSrc,
&audioSnk, 1, id, req);
if (SL_RESULT_SUCCESS != result) {
LOGI( "CreateAudioRecorder failed\n" );
return JNI_FALSE;
}
// realize the audio recorder
result = (*r->recorderObject)->Realize(r->recorderObject, SL_BOOLEAN_FALSE);
if (SL_RESULT_SUCCESS != result) {
LOGI( "AudioRecorder Realize failed: %d\n", result );
return JNI_FALSE;
}
// get the record interface
result = (*r->recorderObject)->GetInterface(r->recorderObject, SL_IID_RECORD, &r->recorderRecord);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// get the buffer queue interface
result = (*r->recorderObject)->GetInterface(r->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&r->recorderBufferQueue);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// register callback on the buffer queue
result = (*r->recorderBufferQueue)->RegisterCallback(r->recorderBufferQueue, bqRecorderCallback, r);
assert(SL_RESULT_SUCCESS == result);
(void)result;
assert( !pthread_mutex_trylock(&audioEngineLock));
// in case already recording, stop recording and clear buffer queue
result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_STOPPED);
assert(SL_RESULT_SUCCESS == result);
(void)result;
result = (*r->recorderBufferQueue)->Clear(r->recorderBufferQueue);
assert(SL_RESULT_SUCCESS == result);
(void)result;
// the buffer is not valid for playback yet
r->recorderSize = 0;
// enqueue an empty buffer to be filled by the recorder
// (for streaming recording, we would enqueue at least 2 empty buffers to start things off)
result = (*r->recorderBufferQueue)->Enqueue(r->recorderBufferQueue, r->recorderBuffer, sizeof(r->recorderBuffer));
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
// which for this code example would indicate a programming error
assert(SL_RESULT_SUCCESS == result);
(void)result;
// start recording
result = (*r->recorderRecord)->SetRecordState(r->recorderRecord, SL_RECORDSTATE_RECORDING);
assert(SL_RESULT_SUCCESS == result);
(void)result;
LOGI( "Complete Init Sound Android\n" );
return r;
}
void CloseSoundAndroid( struct SoundDriverAndroid * r );
int SoundStateAndroid( struct SoundDriverAndroid * soundobject )
{
return ((soundobject->recorderObject)?1:0) | ((soundobject->recorderObject)?2:0);
}
void CloseSoundAndroid( struct SoundDriverAndroid * r )
{
// destroy audio recorder object, and invalidate all associated interfaces
if (r->recorderObject != NULL) {
(*r->recorderObject)->Destroy(r->recorderObject);
r->recorderObject = NULL;
r->recorderRecord = NULL;
r->recorderBufferQueue = NULL;
}
// destroy engine object, and invalidate all associated interfaces
if (r->engineObject != NULL) {
(*r->engineObject)->Destroy(r->engineObject);
r->engineObject = NULL;
r->engineEngine = NULL;
}
}
int AndroidHasPermissions(const char* perm_name);
void AndroidRequestAppPermissions(const char * perm);
void * InitSoundAndroid( SoundCBType cb )
{
int hasperm = AndroidHasPermissions( "RECORD_AUDIO" );
if( !hasperm )
{
AndroidRequestAppPermissions( "RECORD_AUDIO" );
}
struct SoundDriverAndroid * r = (struct SoundDriverAndroid *)malloc( sizeof( struct SoundDriverAndroid ) );
memset( r, 0, sizeof( *r) );
r->CloseFn = CloseSoundAndroid;
r->SoundStateFn = SoundStateAndroid;
r->callback = cb;
r->engineObject = 0;
r->engineEngine = 0;
/*
r->spsPlay = GetParameterI( "samplerate", 44100 );
r->channelsPlay = GetParameterI( "channels", 2 );
r->spsRec = r->spsPlay;
r->channelsRec = r->channelsPlay;
r->playback_handle = 0;
r->record_handle = 0;
r->buffer = GetParameterI( "buffer", 1024 );
r->Android_fmt_s16le = 0;
*/
return InitAndroidSound(r);
}
//Tricky: On Android, this can't actually run before main. Have to manually execute it.
REGISTER_SOUND( AndroidSound, 10, "ANDROID", InitSoundAndroid );