colorchord/colorchord2/main.c

647 lines
16 KiB
C
Raw Permalink Normal View History

2021-03-13 19:58:40 +01:00
// Copyright 2015-2020 <>< Charles Lohr under the ColorChord License.
2015-07-29 07:56:18 +02:00
2021-03-13 19:58:40 +01:00
#if defined( WINDOWS ) || defined( USE_WINDOWS ) || defined( WIN32 ) || defined( WIN64 ) || \
defined( _WIN32 ) || defined( _WIN64 )
2021-06-03 14:28:59 +02:00
#ifdef TCC
#include <winsock2.h>
2021-06-03 14:28:59 +02:00
#endif
2020-05-20 05:19:58 +02:00
#ifndef strdup
#define strdup _strdup
#endif
// define convenient macro to detect windows
#define IS_WINDOWS 1
#else
// this isn't windows
#define IS_WINDOWS 0
#endif
2015-01-07 04:51:39 +01:00
#include "color.h"
2021-03-13 19:58:40 +01:00
#include "configs.h"
#include "decompose.h"
2015-01-07 04:51:39 +01:00
#include "dft.h"
#include "filter.h"
2021-03-13 19:58:40 +01:00
#include "hook.h"
2015-01-07 04:51:39 +01:00
#include "notefinder.h"
2021-03-13 19:58:40 +01:00
#include "os_generic.h"
2015-01-07 04:51:39 +01:00
#include "outdrivers.h"
#include "parameters.h"
2021-03-13 19:58:40 +01:00
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
2015-02-11 07:10:16 +01:00
#define CNFG_IMPLEMENTATION
#include "CNFG.h"
#define CNFA_IMPLEMENTATION
#include "CNFA.h"
2021-03-13 19:58:40 +01:00
// Sound driver.
struct CNFADriver *sd;
2020-05-14 08:14:21 +02:00
int bQuitColorChord = 0;
2019-11-17 11:53:02 +01:00
#ifdef ANDROID
#include <android/log.h>
2021-03-13 19:58:40 +01:00
#include <fcntl.h>
2019-11-17 11:53:02 +01:00
#include <pthread.h>
2021-03-13 19:58:40 +01:00
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
2020-05-11 06:23:04 +02:00
void HandleDestroy()
{
bQuitColorChord = 1;
CNFAClose( sd );
}
2020-05-11 06:23:04 +02:00
2019-11-17 11:53:02 +01:00
#endif
2019-11-17 11:53:02 +01:00
#define GENLINEWIDTH 89
#define GENLINES 67
2020-05-11 06:23:04 +02:00
2021-03-13 19:58:40 +01:00
char genlog[ ( GENLINEWIDTH + 1 ) * ( GENLINES + 1 ) + 2 ] = "log";
int genloglen;
int genloglines;
int genlinelen = 0;
int firstnewline = -1;
2020-05-11 06:23:04 +02:00
// Define application colors RGBA format
2022-10-22 04:57:59 +02:00
#define BACKGROUND_COLOR 0x000000ff
#define LINE_COLOR 0xffffffff
#define TEXT_COLOR 0xffffffff
// Text colors for the debug options at the bottom of the screen
#define ENABLED_COLOR 0xffffffff
#define DISABLED_COLOR 0x800000ff
2021-03-13 19:58:40 +01:00
void example_log_function( int readSize, char *buf )
{
2021-03-13 19:58:40 +01:00
static og_mutex_t *mt;
if ( !mt ) mt = OGCreateMutex();
OGLockMutex( mt );
2021-03-13 19:58:40 +01:00
for ( int i = 0; readSize && i <= readSize && buf[ i ]; i++ )
{
2021-03-13 19:58:40 +01:00
char c = buf[ i ];
if ( c == '\0' ) c = '\n';
if ( ( c != '\n' && genlinelen >= GENLINEWIDTH ) || c == '\n' )
2020-05-11 06:23:04 +02:00
{
genloglines++;
2021-03-13 19:58:40 +01:00
if ( genloglines >= GENLINES )
2020-05-11 06:23:04 +02:00
{
genloglen -= firstnewline + 1;
int offset = firstnewline;
firstnewline = -1;
2021-03-13 19:58:40 +01:00
int k;
for ( k = 0; k < genloglen; k++ )
{
2021-03-13 19:58:40 +01:00
if ( ( genlog[ k ] = genlog[ k + offset + 1 ] ) == '\n' && firstnewline < 0 )
firstnewline = k;
}
2021-03-13 19:58:40 +01:00
genlog[ k ] = 0;
genloglines--;
}
genlinelen = 0;
2021-03-13 19:58:40 +01:00
if ( c != '\n' )
2020-05-11 06:23:04 +02:00
{
2021-03-13 19:58:40 +01:00
genlog[ genloglen + 1 ] = 0;
genlog[ genloglen++ ] = '\n';
2020-05-11 06:23:04 +02:00
}
2021-03-13 19:58:40 +01:00
if ( firstnewline < 0 ) firstnewline = genloglen;
2020-05-11 06:23:04 +02:00
}
2021-03-13 19:58:40 +01:00
genlog[ genloglen + 1 ] = 0;
genlog[ genloglen++ ] = c;
2021-03-13 19:58:40 +01:00
if ( c != '\n' ) genlinelen++;
}
2020-05-11 06:23:04 +02:00
OGUnlockMutex( mt );
2019-11-17 11:53:02 +01:00
}
2021-03-13 19:58:40 +01:00
#if defined( WIN32 ) || defined( USE_WINDOWS )
2016-10-08 20:43:04 +02:00
#define ESCAPE_KEY 0x1B
void HandleDestroy()
{
CNFAClose( sd );
}
2016-10-08 20:43:04 +02:00
#else
#define ESCAPE_KEY 65307
// Stub function for Linux
void HandleDestroy()
{
}
2016-10-08 20:43:04 +02:00
#endif
float DeltaFrameTime = 0;
2021-03-13 21:55:43 +01:00
double Now = 0;
int is_suspended = 0;
int lastfps;
2015-01-07 04:51:39 +01:00
short screenx, screeny;
2021-03-13 19:58:40 +01:00
struct DriverInstances *outdriver[ MAX_OUT_DRIVERS ];
int headless = 0; REGISTER_PARAM( headless, PAINT );
int set_screenx = 640; REGISTER_PARAM( set_screenx, PAINT );
int set_screeny = 480; REGISTER_PARAM( set_screeny, PAINT );
char sound_source[ 16 ]; REGISTER_PARAM( sound_source, PABUFFER );
int cpu_autolimit = 1; REGISTER_PARAM( cpu_autolimit, PAINT );
float cpu_autolimit_interval = 0.016; REGISTER_PARAM( cpu_autolimit_interval, PAFLOAT );
int sample_channel = -1; REGISTER_PARAM( sample_channel, PAINT );
int showfps = 1; REGISTER_PARAM( showfps, PAINT );
2020-05-11 06:23:04 +02:00
2021-03-13 19:58:40 +01:00
#if defined( ANDROID ) || defined( __android__ )
2020-05-11 06:23:04 +02:00
float in_amplitude = 2;
#else
float in_amplitude = 1;
#endif
REGISTER_PARAM( in_amplitude, PAFLOAT );
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
struct NoteFinder *nf;
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
// Sound circular buffer
#define SOUNDCBSIZE 8096
2015-01-07 04:51:39 +01:00
#define MAX_CHANNELS 2
double VisTimeEnd, VisTimeStart;
2021-03-13 19:58:40 +01:00
float sound[ SOUNDCBSIZE ];
int soundhead = 0;
int show_debug = 0;
int show_debug_basic = 0;
2015-01-07 04:51:39 +01:00
int gKey = 0;
extern int force_white;
2015-01-07 04:51:39 +01:00
2020-05-11 06:23:04 +02:00
void RecalcBaseHz()
{
2021-03-13 19:58:40 +01:00
nf->base_hz = 55 * pow( 2, gKey / 12.0 );
ChangeNFParameters( nf );
2020-05-11 06:23:04 +02:00
}
2015-01-07 04:51:39 +01:00
void HandleKey( int keycode, int bDown )
{
char c = toupper( keycode );
2020-05-11 23:00:25 +02:00
#ifdef ANDROID
2021-03-13 19:58:40 +01:00
if ( keycode == 4 && bDown )
2020-05-11 23:00:25 +02:00
{
2021-03-13 19:58:40 +01:00
// Back button.
2020-05-11 23:00:25 +02:00
printf( "Back button pressed\n" );
AndroidSendToBack( 0 );
2020-05-11 23:00:25 +02:00
return;
}
#endif
if( keycode == ESCAPE_KEY ) exit( 0 );
if( c == 'W' ) force_white = bDown;
if( c == 'D' && bDown ) show_debug = !show_debug;
if( c == '9' && bDown ) { gKey--; RecalcBaseHz(); }
if( c == '-' && bDown ) { gKey++; RecalcBaseHz(); }
if( c == '0' && bDown ) { gKey = 0; RecalcBaseHz(); }
if( c == 'E' && bDown ) show_debug_basic = !show_debug_basic;
if( c == 'K' && bDown ) DumpParameters();
2015-01-07 04:51:39 +01:00
printf( "Key: %d -> %d\n", keycode, bDown );
KeyHappened( keycode, bDown );
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
// On Android we want a really basic GUI
2015-01-07 04:51:39 +01:00
void HandleButton( int x, int y, int button, int bDown )
{
printf( "Button: %d,%d (%d) -> %d\n", x, y, button, bDown );
2021-03-13 19:58:40 +01:00
if ( bDown )
2020-05-11 06:23:04 +02:00
{
2021-03-13 19:58:40 +01:00
if ( y < 800 )
2020-05-11 06:23:04 +02:00
{
2021-03-13 19:58:40 +01:00
if ( x < screenx / 3 )
gKey--;
else if ( x < ( screenx * 2 / 3 ) )
2020-05-11 06:23:04 +02:00
gKey = 0;
else
gKey++;
printf( "KEY: %d\n", gKey );
RecalcBaseHz();
}
}
2015-01-07 04:51:39 +01:00
}
void HandleMotion( int x, int y, int mask )
{
}
2021-03-13 19:58:40 +01:00
void SoundCB( struct CNFADriver *sd, short *out, short *in, int framesp, int framesr )
2015-01-07 04:51:39 +01:00
{
2021-05-22 20:45:23 +02:00
int channelin = sd->channelsRec;
int channelout = sd->channelsPlay;
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
// Load the samples into a ring buffer. Split the channels from interleved to one per buffer.
if ( in )
2015-01-07 04:51:39 +01:00
{
2021-03-13 19:58:40 +01:00
for ( int i = 0; i < framesr; i++ )
{
2021-03-13 19:58:40 +01:00
if ( sample_channel < 0 )
2016-05-31 07:11:24 +02:00
{
float fo = 0;
2021-03-13 19:58:40 +01:00
for ( int j = 0; j < channelin; j++ )
2015-02-11 07:10:16 +01:00
{
2021-03-13 19:58:40 +01:00
float f = in[ i * channelin + j ] / 32767.;
if ( f >= -1 && f <= 1 )
fo += f;
else
2021-03-13 19:58:40 +01:00
fo += ( f > 0 ) ? 1 : -1;
}
fo /= channelin;
2021-03-13 19:58:40 +01:00
sound[ soundhead ] = fo * in_amplitude;
2021-05-22 20:45:23 +02:00
soundhead = ( soundhead + 1 ) % SOUNDCBSIZE;
2015-02-11 07:10:16 +01:00
}
else
{
2021-03-13 19:58:40 +01:00
float f = in[ i * channelin + sample_channel ] / 32767.;
if ( f > 1 || f < -1 ) f = ( f > 0 ) ? 1 : -1;
sound[ soundhead ] = f * in_amplitude;
2021-05-22 20:45:23 +02:00
soundhead = ( soundhead + 1 ) % SOUNDCBSIZE;
}
2015-01-07 04:51:39 +01:00
}
2020-05-20 07:38:56 +02:00
SoundEventHappened( framesr, in, 0, channelin );
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
if ( out )
2016-05-31 07:11:24 +02:00
{
2021-05-22 20:45:23 +02:00
memset( out, 0, framesp * channelout );
2020-05-20 07:38:56 +02:00
SoundEventHappened( framesp, out, 1, channelout );
2016-05-31 07:11:24 +02:00
}
2015-01-07 04:51:39 +01:00
}
2019-11-17 11:53:02 +01:00
#ifdef ANDROID
void HandleSuspend()
{
is_suspended = 1;
2019-11-17 11:53:02 +01:00
}
void HandleResume()
{
is_suspended = 0;
2019-11-17 11:53:02 +01:00
}
#endif
// function for calling initilization functions if we are using TCC
#ifdef TCC
2021-03-13 19:58:40 +01:00
void RegisterConstructorFunctions()
{
2020-05-16 08:39:22 +02:00
// Basic Window stuff
2020-05-16 08:39:22 +02:00
REGISTERheadless();
REGISTERset_screenx();
REGISTERset_screeny();
REGISTERsound_source();
REGISTERcpu_autolimit();
REGISTERcpu_autolimit_interval();
2020-05-16 08:39:22 +02:00
REGISTERsample_channel();
REGISTERshowfps();
REGISTERin_amplitude();
// Audio stuff
REGISTERNullCNFA();
REGISTERWinCNFA();
REGISTERcnfa_wasapi();
// Video Stuff
REGISTERnull();
REGISTERDisplayArray();
REGISTERDisplayHIDAPI();
REGISTERDisplayNetwork();
REGISTERDisplayOutDriver();
REGISTERDisplayPie();
REGISTERDisplayRadialPoles();
// block trying to load linux specific displays
#if not IS_WINDOWS
REGISTERDisplayDMX();
REGISTERDisplayFileWrite();
REGISTERDisplaySHM();
REGISTERDisplayUSB2812();
#endif
// Output stuff
REGISTEROutputCells();
REGISTEROutputLinear();
REGISTEROutputProminent();
REGISTEROutputVoronoi();
}
2020-05-16 08:39:22 +02:00
#endif
2021-03-13 19:58:40 +01:00
int main( int argc, char **argv )
{
#ifdef TCC
RegisterConstructorFunctions();
#endif
2020-05-21 07:38:19 +02:00
printf( "Output Drivers:\n" );
2021-03-13 19:58:40 +01:00
for ( int i = 0; i < MAX_OUT_DRIVERS; i++ )
{
2021-03-13 19:58:40 +01:00
if ( ODList[ i ].Name ) printf( "\t%s\n", ODList[ i ].Name );
}
2020-05-21 07:38:19 +02:00
2021-03-13 19:58:40 +01:00
#if defined( WIN32 ) || defined( USE_WINDOWS )
// In case something needs network access.
WSADATA wsaData;
2021-03-13 19:58:40 +01:00
WSAStartup( 0x202, &wsaData );
2019-11-17 11:53:02 +01:00
#elif defined( ANDROID )
2021-05-22 20:45:23 +02:00
int hasperm = AndroidHasPermissions( "READ_EXTERNAL_STORAGE" );
2020-05-20 21:34:57 +02:00
int haspermInternet = AndroidHasPermissions( "INTERNET" );
if ( !hasperm ) AndroidRequestAppPermissions( "READ_EXTERNAL_STORAGE" );
if ( !haspermInternet ) AndroidRequestAppPermissions( "INTERNET" );
#else
2021-03-13 19:58:40 +01:00
// Linux
#endif
gargc = argc;
gargv = argv;
SetupConfigs();
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
// Initialize Rawdraw
2015-01-07 04:51:39 +01:00
int frames = 0;
double ThisTime;
double SecToWait;
2021-05-22 20:45:23 +02:00
double LastFPSTime = OGGetAbsoluteTime();
double LastFrameTime = OGGetAbsoluteTime();
CNFGBGColor = BACKGROUND_COLOR;
2021-03-13 19:58:40 +01:00
// Generate the window title
char title[ 1024 ];
strcpy( title, "Colorchord " );
for ( int i = 1; i < argc; i++ )
{
2021-03-13 19:58:40 +01:00
strcat( title, argv[ i ] );
strcat( title, " " );
}
2021-03-13 19:58:40 +01:00
if ( !headless ) CNFGSetup( title, set_screenx, set_screeny );
2021-03-13 19:58:40 +01:00
char *OutDriverNames = strdup( GetParameterS( "outdrivers", "null" ) );
char *ThisDriver = OutDriverNames;
char *TDStart;
for ( int i = 0; i < MAX_OUT_DRIVERS; i++ )
{
2021-03-13 19:58:40 +01:00
while ( *ThisDriver == ' ' || *ThisDriver == '\t' ) ThisDriver++;
if ( !*ThisDriver ) break;
TDStart = ThisDriver;
2021-03-13 19:58:40 +01:00
while ( *ThisDriver != 0 && *ThisDriver != ',' )
{
2021-03-13 19:58:40 +01:00
if ( *ThisDriver == '\t' || *ThisDriver == ' ' ) *ThisDriver = 0;
ThisDriver++;
}
2021-03-13 19:58:40 +01:00
if ( *ThisDriver )
{
*ThisDriver = 0;
ThisDriver++;
}
2021-05-22 20:45:23 +02:00
printf( "Loading: %s\n", TDStart );
2021-03-13 19:58:40 +01:00
outdriver[ i ] = SetupOutDriver( TDStart );
}
2021-03-13 19:58:40 +01:00
free( OutDriverNames );
2015-01-07 04:51:39 +01:00
2021-05-22 20:45:23 +02:00
do {
#if IS_WINDOWS
const char *record_dev_name = "defaultRender";
#else
const char *record_dev_name = "@DEFAULT_MONITOR@";
#endif
2021-03-13 19:58:40 +01:00
// Initialize Sound
sd = CNFAInit( sound_source, "colorchord", &SoundCB, GetParameterI( "samplerate", 44100 ),
GetParameterI( "samplerate", 44100 ), GetParameterI( "channels", 2 ),
GetParameterI( "channels", 2 ), GetParameterI( "buffer", 1024 ),
GetParameterS( "devplay", "default" ), GetParameterS( "devrecord", record_dev_name ),
NULL );
2020-05-11 06:23:04 +02:00
2021-03-13 19:58:40 +01:00
if ( sd ) break;
2021-05-22 20:45:23 +02:00
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 10;
CNFGPenY = 100;
2020-05-11 06:23:04 +02:00
CNFGHandleInput();
CNFGClearFrame();
CNFGDrawText( "Colorchord must be used with sound. Sound not available.", 10 );
2020-05-11 06:23:04 +02:00
CNFGSwapBuffers();
2021-03-13 19:58:40 +01:00
OGSleep( 1 );
} while ( 1 );
2020-05-21 04:40:53 +02:00
nf = CreateNoteFinder( sd->spsRec );
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
// Once everything was reinitialized, re-read the ini files.
SetEnvValues( 1 );
2020-05-11 06:23:04 +02:00
printf( "================================================= Set Up\n" );
Now = OGGetAbsoluteTime();
double Last = Now;
2021-03-13 19:58:40 +01:00
while ( !bQuitColorChord )
2015-01-07 04:51:39 +01:00
{
2021-03-13 19:58:40 +01:00
char stt[ 1024 ];
// Handle Rawdraw frame swappign
2015-02-11 07:10:16 +01:00
Now = OGGetAbsoluteTime();
DeltaFrameTime = Now - Last;
2021-03-13 19:58:40 +01:00
if ( !headless )
2015-02-11 07:10:16 +01:00
{
CNFGHandleInput();
CNFGClearFrame();
CNFGColor( LINE_COLOR );
2015-02-11 07:10:16 +01:00
CNFGGetDimensions( &screenx, &screeny );
}
2015-01-07 04:51:39 +01:00
2021-03-13 19:58:40 +01:00
RunNoteFinder( nf, sound, ( soundhead - 1 + SOUNDCBSIZE ) % SOUNDCBSIZE, SOUNDCBSIZE );
// Done all ColorChord work.
2015-01-07 04:51:39 +01:00
2015-06-26 23:00:04 +02:00
2015-01-07 04:51:39 +01:00
VisTimeStart = OGGetAbsoluteTime();
2015-06-26 23:00:04 +02:00
2021-03-13 19:58:40 +01:00
// call the output drivers with the updated note finder data
for ( int i = 0; i < MAX_OUT_DRIVERS; i++ )
2015-06-26 23:00:04 +02:00
{
2021-03-13 19:58:40 +01:00
if ( force_white ) memset( OutLEDs, 0x7f, MAX_LEDS * 3 );
if ( outdriver[ i ] ) outdriver[ i ]->Func( outdriver[ i ]->id, nf );
2015-06-26 23:00:04 +02:00
}
2015-01-07 04:51:39 +01:00
VisTimeEnd = OGGetAbsoluteTime();
2015-06-26 23:00:04 +02:00
2021-03-13 19:58:40 +01:00
if ( !headless )
2015-01-07 04:51:39 +01:00
{
2021-03-13 19:58:40 +01:00
// Handle outputs.
2021-05-22 20:45:23 +02:00
int freqbins = nf->freqbins;
2021-03-13 19:58:40 +01:00
int note_peaks = freqbins / 2;
2021-05-22 20:45:23 +02:00
int freqs = freqbins * nf->octaves;
2015-02-11 07:10:16 +01:00
2021-03-13 19:58:40 +01:00
// Do a bunch of debugging.
if ( show_debug_basic && !is_suspended )
2015-01-07 04:51:39 +01:00
{
CNFGColor( TEXT_COLOR );
2021-03-13 19:58:40 +01:00
for ( int i = 0; i < nf->dists_count; i++ )
2015-02-11 07:10:16 +01:00
{
2021-03-13 19:58:40 +01:00
// Move over 0.5 for visual purposes. The means is correct.
CNFGPenX = ( nf->dists[ i ].mean + 0.5 ) / freqbins * screenx;
CNFGPenY = 400 - nf->dists[ i ].amp * 150.0 / nf->dists[ i ].sigma;
sprintf( stt, "%f\n%f\n", nf->dists[ i ].mean, nf->dists[ i ].amp );
2015-02-11 07:10:16 +01:00
CNFGDrawText( stt, 2 );
}
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
// Draw the folded bins
for ( int bin = 0; bin < freqbins; bin++ )
2015-02-11 07:10:16 +01:00
{
2021-05-22 20:45:23 +02:00
const float x0 = bin / (float)freqbins * (float)screenx;
const float x1 = ( bin + 1 ) / (float)freqbins * (float)screenx;
const float amp = nf->folded_bins[ bin ] * 250.0;
const float note = (float)( bin + 0.5 ) / freqbins;
CNFGDialogColor = CCtoHEX( note, 1.0, 1.0 );
2021-03-13 19:58:40 +01:00
CNFGDrawBox( x0, 400 - amp, x1, 400 );
2015-02-11 07:10:16 +01:00
}
2021-03-13 19:58:40 +01:00
// Draw the note peaks
for ( int peak = 0; peak < note_peaks; peak++ )
2015-02-11 07:10:16 +01:00
{
2021-03-13 19:58:40 +01:00
if ( nf->note_amplitudes_out[ peak ] < 0 ) continue;
2021-05-22 20:45:23 +02:00
float note = (float)nf->note_positions[ peak ] / freqbins;
2020-05-18 01:19:21 +02:00
CNFGDialogColor = CCtoHEX( note, 1.0, 1.0 );
2021-05-22 20:45:23 +02:00
const int x1 = ( (float)peak / note_peaks ) * screenx;
const int x2 = ( (float)( peak + 1 ) / note_peaks ) * screenx;
const int y1 = 480 - nf->note_amplitudes_out[ peak ] * 100;
const int y2 = 480;
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
CNFGDrawBox( x1, y1, x2, y2 );
2021-05-22 20:45:23 +02:00
CNFGPenX = ( (float)( peak + .4 ) / note_peaks ) * screenx;
2015-02-11 07:10:16 +01:00
CNFGPenY = screeny - 30;
2021-03-13 20:02:53 +01:00
sprintf( stt, "%d\n%0.0f", nf->enduring_note_id[ peak ],
nf->note_amplitudes2[ peak ] * 1000.0 );
CNFGColor( TEXT_COLOR );
2015-02-11 07:10:16 +01:00
CNFGDrawText( stt, 2 );
}
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
// Let's draw the o-scope.
2021-11-23 22:29:42 +01:00
int lasty;
2021-11-23 22:53:59 +01:00
int thissoundhead = ( soundhead - 1 + SOUNDCBSIZE ) % SOUNDCBSIZE;
2021-11-23 22:29:42 +01:00
int thisy = sound[ thissoundhead ] * -128 + 128;
for ( int i = screenx - 1; i > 0; i-- )
2015-02-11 07:10:16 +01:00
{
2021-05-22 20:45:23 +02:00
lasty = thisy;
2021-03-13 19:58:40 +01:00
thissoundhead = ( thissoundhead - 1 + SOUNDCBSIZE ) % SOUNDCBSIZE;
2021-11-23 22:53:59 +01:00
thisy = sound[ thissoundhead ] * -128 + 128;
2021-11-23 22:29:42 +01:00
CNFGTackSegment( i, lasty, i - 1, thisy );
2015-02-11 07:10:16 +01:00
}
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
// Extra debugging?
if ( show_debug && !is_suspended )
2015-01-07 04:51:39 +01:00
{
2021-03-13 19:58:40 +01:00
// Draw the histogram
2015-02-11 07:10:16 +01:00
float lasthistval;
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
for ( int x_val = -1; x_val < screenx; x_val++ )
2015-02-11 07:10:16 +01:00
{
2021-03-13 19:58:40 +01:00
// Calculate the value of the histogram at the current screen position
2021-05-22 20:45:23 +02:00
float hist_point = (float)x_val / (float)screenx * freqbins - 0.5;
2021-03-13 19:58:40 +01:00
float thishistval =
CalcHistAt( hist_point, nf->freqbins, nf->dists, nf->dists_count );
// Display the value on the screen
const short y = 400 - lasthistval * 250.0;
if ( x_val >= 0 ) CNFGTackSegment( x_val, y, x_val + 1, y );
2015-02-11 07:10:16 +01:00
lasthistval = thishistval;
}
CNFGColor( LINE_COLOR );
2021-03-13 19:58:40 +01:00
// Draw the bins
2021-03-13 20:02:53 +01:00
for ( int bin = 0; bin < freqs; bin++ )
2015-02-11 07:10:16 +01:00
{
2021-05-22 20:45:23 +02:00
float x0 = bin / (float)freqs * (float)screenx;
float x1 = ( bin + 1 ) / (float)freqs * (float)screenx;
float amp = nf->outbins[ bin ] * 250.0;
float note = (float)bin / freqbins;
2021-03-13 19:58:40 +01:00
CNFGDialogColor = CCtoHEX( note, 1.0, 1.0 );
2015-02-11 07:10:16 +01:00
CNFGDrawBox( x0, 0, x1, amp );
}
CNFGColor( TEXT_COLOR );
2021-03-13 19:58:40 +01:00
char stdebug[ 1024 ];
2015-02-11 07:10:16 +01:00
sprintf( stdebug, "DFT:%8.2fms\nFLT:%8.2f\nDEC:%8.2f\nFNL:%8.2f\nDPY:%8.2f",
2021-03-13 19:58:40 +01:00
( nf->DFTTime - nf->StartTime ) * 1000, ( nf->FilterTime - nf->DFTTime ) * 1000,
( nf->DecomposeTime - nf->FilterTime ) * 1000,
( nf->FinalizeTime - nf->DecomposeTime ) * 1000,
( VisTimeEnd - VisTimeStart ) * 1000 );
2015-02-11 07:10:16 +01:00
CNFGPenX = 50;
CNFGPenY = 50;
CNFGDrawText( stdebug, 2 );
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
if ( !is_suspended )
{
CNFGColor( show_debug ? ENABLED_COLOR : DISABLED_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 0;
CNFGPenY = screeny - 10;
CNFGDrawText( "Extra Debug (D)", 2 );
2015-01-07 04:51:39 +01:00
CNFGColor( show_debug_basic ? ENABLED_COLOR : DISABLED_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 120;
CNFGPenY = screeny - 10;
CNFGDrawText( "Basic Debug (E)", 2 );
2015-01-07 04:51:39 +01:00
CNFGColor( show_debug_basic ? ENABLED_COLOR : DISABLED_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 240;
CNFGPenY = screeny - 10;
sprintf( stt, "[9] Key: %d [0] (%3.1f) [-]", gKey, nf->base_hz );
CNFGDrawText( stt, 2 );
2015-01-07 04:51:39 +01:00
CNFGColor( TEXT_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 440;
CNFGPenY = screeny - 10;
sprintf( stt, "FPS: %d", lastfps );
CNFGDrawText( stt, 2 );
2020-05-11 06:23:04 +02:00
#ifdef ANDROID
CNFGColor( TEXT_COLOR );
2021-03-13 19:58:40 +01:00
CNFGPenX = 10;
CNFGPenY = 600;
CNFGDrawText( genlog, 3 );
2020-05-11 06:23:04 +02:00
#endif
CNFGSwapBuffers();
}
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
// Finish Rawdraw with FPS counter, and a nice delay loop.
2015-01-07 04:51:39 +01:00
frames++;
2015-02-11 07:10:16 +01:00
2015-01-07 04:51:39 +01:00
ThisTime = OGGetAbsoluteTime();
2021-03-13 19:58:40 +01:00
if ( ThisTime > LastFPSTime + 1 && showfps )
2015-01-07 04:51:39 +01:00
{
lastfps = frames;
2021-05-22 20:45:23 +02:00
frames = 0;
2021-03-13 19:58:40 +01:00
LastFPSTime += 1;
2015-01-07 04:51:39 +01:00
}
2021-03-13 19:58:40 +01:00
if ( cpu_autolimit )
{
2018-05-08 06:04:49 +02:00
SecToWait = cpu_autolimit_interval - ( ThisTime - LastFrameTime );
LastFrameTime += cpu_autolimit_interval;
2021-03-13 19:58:40 +01:00
if ( SecToWait < -.1 ) LastFrameTime = ThisTime - .1;
2021-05-22 20:45:23 +02:00
if ( SecToWait > 0 ) OGUSleep( (int)( SecToWait * 1000000 ) );
}
2021-03-13 19:58:40 +01:00
if ( !is_suspended ) SetEnvValues( 0 );
2020-05-11 23:00:25 +02:00
Last = Now;
2015-01-07 04:51:39 +01:00
}
}