Commit b107cce0 authored by Gargaj's avatar Gargaj
Browse files

add option to select audio device

also update miniaudio to v0.10.4
parent c9f5594a
......@@ -29,11 +29,14 @@ You can configure Bonzomatic by creating a `config.json` and placing it next to
The file can have the following contents: (all fields are optional)
``` javascript
{
"window":{ // default window size / state, if there's a setup dialog, it will override it
"window":{ // default window size / state; if there's a setup dialog, it will override it
"width":1920,
"height":1080,
"fullscreen":true,
},
"audio":{ // default audio device settings; if there's a setup dialog, it will override it
"useInput":false, // if true, use line-in/mic/...; if false, attempt to create a loopback device and use stereo out
},
"font":{ // all paths in the file are also relative to the binary, but again, can be absolute paths if that's more convenient
"file":"Input-Regular_(InputMono-Medium).ttf",
"size":16,
......@@ -80,7 +83,7 @@ The file can have the following contents: (all fields are optional)
"builtin": "44FF88",
"preprocessor": "C0C0C0",
"selection": "C06699CC", // background color when selecting text
"charBackground": "C0000000", // if set, this value will be used (instead of gui opacity) behind characters
"charBackground": "C0000000", // if set, this value will be used (instead of gui opacity) behind characters
},
"postExitCmd":"copy_to_dropbox.bat" // this command gets ran when you quit Bonzomatic, and the shader filename gets passed to it as first parameter. Use this to take regular backups.
}
......
// Microsoft Visual C++ generated resource script.
//
#include <windows.h>
#include "resource.h"
#define IDC_STATIC -1
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1250)
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_SETUP DIALOGEX 0, 0, 186, 92
IDD_SETUP DIALOGEX 0, 0, 186, 104
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "mlat design"
FONT 8, "Tahoma", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "Run",IDOK,60,66,116,14
PUSHBUTTON "Cancel",IDCANCEL,6,66,50,14
DEFPUSHBUTTON "Run",IDOK,60,84,116,14
PUSHBUTTON "Cancel",IDCANCEL,6,84,50,14
RTEXT "Resolution:",IDC_STATIC,7,22,65,10
COMBOBOX IDC_RESOLUTION,83,20,91,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
RTEXT "Fullscreen:",IDC_STATIC,7,36,65,10
......@@ -24,6 +38,8 @@ BEGIN
CTEXT "BONZOMATIC",IDC_STATIC,5,8,175,10
RTEXT "Vertical sync:",IDC_STATIC,7,50,65,10
CONTROL "",IDC_VSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,83,50,9,10
RTEXT "Audio source:",IDC_STATIC,6,64,65,10
COMBOBOX IDC_AUDIOSOURCE,82,62,91,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
END
......@@ -37,11 +53,21 @@ GUIDELINES DESIGNINFO
BEGIN
IDD_SETUP, DIALOG
BEGIN
BOTTOMMARGIN, 77
BOTTOMMARGIN, 89
END
END
#endif // APSTUDIO_INVOKED
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Hungarian (Hungary) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HUN)
LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT
#pragma code_page(1250)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
......@@ -76,8 +102,8 @@ END
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_APPLICATION ICON "icon.ico"
IDI_APPLICATION ICON "icon.ico"
#endif // Hungarian (Hungary) resources
/////////////////////////////////////////////////////////////////////////////
......
This diff is collapsed.
![miniaudio](http://dred.io/img/miniaudio_wide.png)
![miniaudio](https://miniaud.io/img/miniaudio_wide.png)
miniaudio (formerly mini_al) is a single file library for audio playback and capture. It's written
in C (compilable as C++) and released into the public domain.
miniaudio is a single file library for audio playback and capture. It's written in C (compilable as C++) and
released into the public domain.
Features
========
- A simple build system.
- It should Just Work out of the box, without the need to download and install any dependencies.
- A simple API.
- Supports playback, capture and full-duplex.
- Data conversion.
- Sample format conversion, with optional dithering.
- Sample rate conversion.
- Channel mapping and channel conversion (stereo to 5.1, etc.)
- MP3, Vorbis, FLAC and WAV decoding.
- This depends on external single file libraries which can be found in the "extras" folder.
- Liberally licensed, with your choice of either public domain or MIT No Attribution for those regions who don't
recognize public domain.
- Everything is implemented in a single file for easy integration into your source tree.
- No external dependencies except for the C standard library and backend APIs.
- Written in C89 and compilable as C++ which should enable miniaudio to work with almost all compilers.
- Supports all major desktop and mobile platforms, with multiple backends for maximum compatibility.
- Supports playback, capture, full-duplex and loopback (WASAPI only).
- Device enumeration for connecting to specific devices, not just defaults.
- Connect to multiple devices at once.
- Shared and exclusive mode on supported backends.
- Backend-specific configuration options.
- Device capability querying.
- Automatic data conversion between your application and the internal device.
- Sample format conversion with optional dithering.
- Channel conversion and channel mapping.
- Resampling with support for multiple algorithms.
- Simple linear resampling with anti-aliasing.
- Optional Speex resampling (must opt-in).
- Filters.
- Biquad
- Low-pass (first, second and high order)
- High-pass (first, second and high order)
- Second order band-pass
- Second order notch
- Second order peaking
- Second order low shelf
- Second order high shelf
- Waveform generation.
- Sine
- Square
- Triangle
- Sawtooth
- Noise generation.
- White
- Pink
- Brownian
- Decoding (requires external single-file libraries).
- WAV via dr_wav
- FLAC via dr_flac
- MP3 via dr_mp3
- Vorbis via stb_vorbis
- Encoding (requires external single-file libraries).
- WAV via dr_wav
- Lock free ring buffer (single producer, single consumer).
Supported Platforms
......@@ -50,12 +84,13 @@ Backends
Building
======
Do the following in one source file:
```
```c
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
```
Then just compile. There's no need to install any dependencies. On Windows and macOS there's no need to link
to anything. On Linux and BSD, just link to -lpthread, -lm and -ldl.
to anything. On Linux just link to -lpthread, -lm and -ldl. On BSD just link to -lpthread and -lm. On iOS you
need to compile as Objective-C.
Simple Playback Example
......@@ -63,11 +98,11 @@ Simple Playback Example
```c
#define DR_FLAC_IMPLEMENTATION
#include "../extras/dr_flac.h" // Enables FLAC decoding.
#include "../extras/dr_flac.h" /* Enables FLAC decoding. */
#define DR_MP3_IMPLEMENTATION
#include "../extras/dr_mp3.h" // Enables MP3 decoding.
#include "../extras/dr_mp3.h" /* Enables MP3 decoding. */
#define DR_WAV_IMPLEMENTATION
#include "../extras/dr_wav.h" // Enables WAV decoding.
#include "../extras/dr_wav.h" /* Enables WAV decoding. */
#define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h"
......@@ -88,26 +123,29 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
int main(int argc, char** argv)
{
ma_result result;
ma_decoder decoder;
ma_device_config deviceConfig;
ma_device device;
if (argc < 2) {
printf("No input file.\n");
return -1;
}
ma_decoder decoder;
ma_result result = ma_decoder_init_file(argv[1], NULL, &decoder);
result = ma_decoder_init_file(argv[1], NULL, &decoder);
if (result != MA_SUCCESS) {
return -2;
}
ma_device_config config = ma_device_config_init(ma_device_type_playback);
config.playback.format = decoder.outputFormat;
config.playback.channels = decoder.outputChannels;
config.sampleRate = decoder.outputSampleRate;
config.dataCallback = data_callback;
config.pUserData = &decoder;
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = decoder.outputFormat;
deviceConfig.playback.channels = decoder.outputChannels;
deviceConfig.sampleRate = decoder.outputSampleRate;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &decoder;
ma_device device;
if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n");
ma_decoder_uninit(&decoder);
return -3;
......@@ -139,17 +177,12 @@ miniaudio includes a decoding API which supports the following backends:
- WAV via [dr_wav](https://github.com/mackron/dr_libs/blob/master/dr_wav.h)
- Vorbis via [stb_vorbis](https://github.com/nothings/stb/blob/master/stb_vorbis.c)
Copies of these libraries can be found in the "extras" folder. You may also want to look at the
libraries below, but they are not supported by the miniaudio decoder API. If you know of any other
single file libraries I can add to this list, let me know. Preferably public domain or MIT.
- [minimp3](https://github.com/lieff/minimp3)
- [jar_mod](https://github.com/kd7tck/jar/blob/master/jar_mod.h)
- [jar_xm](https://github.com/kd7tck/jar/blob/master/jar_xm.h)
Copies of these libraries can be found in the "extras" folder.
To enable support for a decoding backend, all you need to do is #include the header section of the
relevant backend library before the implementation of miniaudio, like so:
```
```c
#include "dr_flac.h" // Enables FLAC decoding.
#include "dr_mp3.h" // Enables MP3 decoding.
#include "dr_wav.h" // Enables WAV decoding.
......@@ -162,7 +195,7 @@ A decoder can be initialized from a file with `ma_decoder_init_file()`, a block
`ma_decoder_init_memory()`, or from data delivered via callbacks with `ma_decoder_init()`. Here
is an example for loading a decoder from a file:
```
```c
ma_decoder decoder;
ma_result result = ma_decoder_init_file("MySong.mp3", NULL, &decoder);
if (result != MA_SUCCESS) {
......@@ -178,7 +211,7 @@ When initializing a decoder, you can optionally pass in a pointer to a `ma_decod
(the `NULL` argument in the example above) which allows you to configure the output format, channel
count, sample rate and channel map:
```
```c
ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 2, 48000);
```
......@@ -187,13 +220,13 @@ decoding backend.
Data is read from the decoder as PCM frames:
```
```c
ma_uint64 framesRead = ma_decoder_read_pcm_frames(pDecoder, pFrames, framesToRead);
```
You can also seek to a specific frame like so:
```
```c
ma_result result = ma_decoder_seek_to_pcm_frame(pDecoder, targetFrame);
if (result != MA_SUCCESS) {
return false; // An error occurred.
......@@ -216,3 +249,17 @@ etc.
The `ma_decoder_init_file()` API will try using the file extension to determine which decoding
backend to prefer.
Unofficial Bindings
===================
The projects below offer bindings for other languages which you may be interested in. Note that these
are unofficial and are not maintained as part of this repository. If you encounter a binding-specific
bug, please post a bug report to the specific project. If you've written your own bindings let me know
and I'll consider adding it to this list.
Language | Project
---------|--------
Python | [pyminiaudio](https://github.com/irmen/pyminiaudio)
Go | [malgo](https://github.com/gen2brain/malgo)
This diff is collapsed.
#define FFT_SIZE 1024
typedef struct
{
bool bUseRecordingDevice;
void * pDeviceID;
} FFT_SETTINGS;
namespace FFT
{
typedef void (*FFT_ENUMERATE_FUNC)( const bool bIsCaptureDevice, const char * szDeviceName, void * pDeviceID, void * pUserContext );
extern float fAmplification;
bool Open();
void EnumerateDevices( FFT_ENUMERATE_FUNC pEnumerationFunction, void * pUserContext );
bool Create();
bool Destroy();
bool Open( FFT_SETTINGS * pSettings );
bool GetFFT( float * _samples );
void Close();
}
\ No newline at end of file
namespace SetupDialog
{
typedef struct
{
RENDERER_SETTINGS sRenderer;
FFT_SETTINGS sFFT;
} SETTINGS;
bool Open( SETTINGS * pSettings );
}
\ No newline at end of file
......@@ -18,6 +18,7 @@
#include "UniConversion.h"
#include "jsonxx.h"
#include "Capture.h"
#include "SetupDialog.h"
unsigned int ParseColor(const std::string& color) {
if (color.size() < 6 || color.size() > 8) return 0xFFFFFFFF;
......@@ -97,36 +98,48 @@ int main(int argc, const char *argv[])
options.parse( szConfig );
}
RENDERER_SETTINGS settings;
settings.bVsync = false;
FFT::Create();
SetupDialog::SETTINGS settings;
settings.sFFT.bUseRecordingDevice = true;
settings.sFFT.pDeviceID = NULL;
if (options.has<jsonxx::Object>("audio"))
{
if (options.get<jsonxx::Object>("audio").has<jsonxx::Number>("useInput"))
settings.sFFT.bUseRecordingDevice = options.get<jsonxx::Object>("audio").get<jsonxx::Boolean>("useInput");
}
settings.sRenderer.bVsync = false;
#ifdef _DEBUG
settings.nWidth = 1280;
settings.nHeight = 720;
settings.windowMode = RENDERER_WINDOWMODE_WINDOWED;
settings.sRenderer.nWidth = 1280;
settings.sRenderer.nHeight = 720;
settings.sRenderer.windowMode = RENDERER_WINDOWMODE_WINDOWED;
#else
settings.nWidth = 1920;
settings.nHeight = 1080;
settings.windowMode = RENDERER_WINDOWMODE_FULLSCREEN;
settings.sRenderer.nWidth = 1920;
settings.sRenderer.nHeight = 1080;
settings.sRenderer.windowMode = RENDERER_WINDOWMODE_FULLSCREEN;
if (options.has<jsonxx::Object>("window"))
{
if (options.get<jsonxx::Object>("window").has<jsonxx::Number>("width"))
settings.nWidth = options.get<jsonxx::Object>("window").get<jsonxx::Number>("width");
settings.sRenderer.nWidth = options.get<jsonxx::Object>("window").get<jsonxx::Number>("width");
if (options.get<jsonxx::Object>("window").has<jsonxx::Number>("height"))
settings.nHeight = options.get<jsonxx::Object>("window").get<jsonxx::Number>("height");
settings.sRenderer.nHeight = options.get<jsonxx::Object>("window").get<jsonxx::Number>("height");
if (options.get<jsonxx::Object>("window").has<jsonxx::Boolean>("fullscreen"))
settings.windowMode = options.get<jsonxx::Object>("window").get<jsonxx::Boolean>("fullscreen") ? RENDERER_WINDOWMODE_FULLSCREEN : RENDERER_WINDOWMODE_WINDOWED;
settings.sRenderer.windowMode = options.get<jsonxx::Object>("window").get<jsonxx::Boolean>("fullscreen") ? RENDERER_WINDOWMODE_FULLSCREEN : RENDERER_WINDOWMODE_WINDOWED;
}
if (!Renderer::OpenSetupDialog( &settings ))
if (!SetupDialog::Open( &settings ))
{
return -1;
}
#endif
if (!Renderer::Open( &settings ))
if (!Renderer::Open( &settings.sRenderer ))
{
printf("Renderer::Open failed\n");
return -1;
}
if (!FFT::Open())
if (!FFT::Open( &settings.sFFT ))
{
printf("FFT::Open() failed, continuing anyway...\n");
//return -1;
......@@ -285,7 +298,7 @@ int main(int argc, const char *argv[])
printf("Couldn't find any of the default fonts. Please specify one in config.json\n");
return -1;
}
if (!Capture::Open(settings))
if (!Capture::Open(settings.sRenderer))
{
printf("Initializing capture system failed!\n");
return 0;
......@@ -352,12 +365,12 @@ int main(int argc, const char *argv[])
bool bTexPreviewVisible = true;
editorOptions.rect = Scintilla::PRectangle( nMargin, nMargin, settings.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.nHeight - nMargin * 2 - nDebugOutputHeight );
editorOptions.rect = Scintilla::PRectangle( nMargin, nMargin, settings.sRenderer.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.sRenderer.nHeight - nMargin * 2 - nDebugOutputHeight );
ShaderEditor mShaderEditor( surface );
mShaderEditor.Initialise( editorOptions );
mShaderEditor.SetText( szShader );
editorOptions.rect = Scintilla::PRectangle( nMargin, settings.nHeight - nMargin - nDebugOutputHeight, settings.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.nHeight - nMargin );
editorOptions.rect = Scintilla::PRectangle( nMargin, settings.sRenderer.nHeight - nMargin - nDebugOutputHeight, settings.sRenderer.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.sRenderer.nHeight - nMargin );
ShaderEditor mDebugOutput( surface );
mDebugOutput.Initialise( editorOptions );
mDebugOutput.SetText( "" );
......@@ -412,14 +425,14 @@ int main(int argc, const char *argv[])
{
if (bTexPreviewVisible)
{
mShaderEditor.SetPosition( Scintilla::PRectangle( nMargin, nMargin, settings.nWidth - nMargin, settings.nHeight - nMargin * 2 - nDebugOutputHeight ) );
mDebugOutput .SetPosition( Scintilla::PRectangle( nMargin, settings.nHeight - nMargin - nDebugOutputHeight, settings.nWidth - nMargin, settings.nHeight - nMargin ) );
mShaderEditor.SetPosition( Scintilla::PRectangle( nMargin, nMargin, settings.sRenderer.nWidth - nMargin, settings.sRenderer.nHeight - nMargin * 2 - nDebugOutputHeight ) );
mDebugOutput .SetPosition( Scintilla::PRectangle( nMargin, settings.sRenderer.nHeight - nMargin - nDebugOutputHeight, settings.sRenderer.nWidth - nMargin, settings.sRenderer.nHeight - nMargin ) );
bTexPreviewVisible = false;
}
else
{
mShaderEditor.SetPosition( Scintilla::PRectangle( nMargin, nMargin, settings.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.nHeight - nMargin * 2 - nDebugOutputHeight ) );
mDebugOutput .SetPosition( Scintilla::PRectangle( nMargin, settings.nHeight - nMargin - nDebugOutputHeight, settings.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.nHeight - nMargin ) );
mShaderEditor.SetPosition( Scintilla::PRectangle( nMargin, nMargin, settings.sRenderer.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.sRenderer.nHeight - nMargin * 2 - nDebugOutputHeight ) );
mDebugOutput .SetPosition( Scintilla::PRectangle( nMargin, settings.sRenderer.nHeight - nMargin - nDebugOutputHeight, settings.sRenderer.nWidth - nMargin - nTexPreviewWidth - nMargin, settings.sRenderer.nHeight - nMargin ) );
bTexPreviewVisible = true;
}
}
......@@ -466,7 +479,7 @@ int main(int argc, const char *argv[])
Renderer::keyEventBufferCount = 0;
Renderer::SetShaderConstant( "fGlobalTime", time );
Renderer::SetShaderConstant( "v2Resolution", settings.nWidth, settings.nHeight );
Renderer::SetShaderConstant( "v2Resolution", settings.sRenderer.nWidth, settings.sRenderer.nHeight );
for (std::map<int,std::string>::iterator it = midiRoutes.begin(); it != midiRoutes.end(); it++)
{
......@@ -524,8 +537,8 @@ int main(int argc, const char *argv[])
if (bTexPreviewVisible)
{
int y1 = nMargin;
int x1 = settings.nWidth - nMargin - nTexPreviewWidth;
int x2 = settings.nWidth - nMargin;
int x1 = settings.sRenderer.nWidth - nMargin - nTexPreviewWidth;
int x2 = settings.sRenderer.nWidth - nMargin;
for (std::map<std::string, Renderer::Texture*>::iterator it = textures.begin(); it != textures.end(); it++)
{
int y2 = y1 + nTexPreviewWidth * (it->second->height / (float)it->second->width);
......@@ -592,6 +605,8 @@ int main(int argc, const char *argv[])
Misc::ExecuteCommand( sPostExitCmd.c_str(), Renderer::defaultShaderFilename );
}
FFT::Destroy();
Misc::PlatformShutdown();
return 0;
......
......@@ -14,6 +14,7 @@ namespace FFT
ma_device captureDevice;
float sampleBuf[ FFT_SIZE * 2 ];
float fAmplification = 1.0f;
bool bCreated = false;
void OnLog( ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message )
{
......@@ -37,12 +38,41 @@ namespace FFT
}
}
bool Open()
void EnumerateDevices( FFT_ENUMERATE_FUNC pEnumerationFunction, void * pUserContext )
{
memset( sampleBuf, 0, sizeof( float ) * FFT_SIZE * 2 );
if (!bCreated)
{
return;
}
fftcfg = kiss_fftr_alloc( FFT_SIZE * 2, false, NULL, NULL );
ma_device_info * pPlaybackDevices = NULL;
ma_device_info * pCaptureDevices = NULL;
ma_uint32 nPlaybackDeviceCount = 0;
ma_uint32 nCaptureDeviceCount = 0;
ma_result result = ma_context_get_devices(&context, &pPlaybackDevices, &nPlaybackDeviceCount, &pCaptureDevices, &nCaptureDeviceCount);
if (result != MA_SUCCESS) {
printf("[FFT] Failed to enumerate audio devices: %d\n", result);
return;
}
pEnumerationFunction( true, "<default device>", NULL, pUserContext );
for (ma_uint32 i = 0; i < nCaptureDeviceCount; i++)
{
pEnumerationFunction( true, pCaptureDevices[i].name, &pCaptureDevices[i].id, pUserContext );
}
if (ma_is_loopback_supported(context.backend))
{
pEnumerationFunction( false, "<default device>", NULL, pUserContext );
for (ma_uint32 i = 0; i < nPlaybackDeviceCount; i++)
{
pEnumerationFunction( false, pPlaybackDevices[i].name, &pPlaybackDevices[i].id, pUserContext );
}
}
}
bool Create()
{
bCreated = false;
ma_context_config context_config = ma_context_config_init();
context_config.logCallback = OnLog;
ma_result result = ma_context_init( NULL, 0, &context_config, &context );
......@@ -53,28 +83,57 @@ namespace FFT
}
printf( "[FFT] MAL context initialized, backend is '%s'\n", ma_get_backend_name( context.backend ) );
bCreated = true;
return true;
}
bool Destroy()
{
if (!bCreated)
{
return false;
}
ma_context_uninit( &context );
bCreated = false;
ma_device_config config = ma_device_config_init( ma_device_type_capture );
config.capture.pDeviceID = NULL;
return true;
}
bool Open( FFT_SETTINGS * pSettings )
{
if (!bCreated)
{
return false;
}
memset( sampleBuf, 0, sizeof( float ) * FFT_SIZE * 2 );
fftcfg = kiss_fftr_alloc( FFT_SIZE * 2, false, NULL, NULL );
bool useLoopback = ma_is_loopback_supported( context.backend ) && !pSettings->bUseRecordingDevice;
ma_device_config config = ma_device_config_init( useLoopback ? ma_device_type_loopback : ma_device_type_capture );
config.capture.pDeviceID = (ma_device_id*)pSettings->pDeviceID;
config.capture.format = ma_format_f32;
config.capture.channels = 2;
config.sampleRate = 44100;
config.dataCallback = OnReceiveFrames;
config.pUserData = NULL;
result = ma_device_init( &context, &config, &captureDevice );
ma_result result = ma_device_init( &context, &config, &captureDevice );
if ( result != MA_SUCCESS )
{
ma_context_uninit( &context );
printf( "[FFT] Failed to initialize capture device: %d\n", result );
return false;
}
printf( "[FFT] Selected capture device: %s\n", captureDevice.capture.name );
result = ma_device_start( &captureDevice );
if ( result != MA_SUCCESS )
{
ma_device_uninit( &captureDevice );
ma_context_uninit( &context );
printf( "[FFT] Failed to start capture device: %d\n", result );
return false;
}
......@@ -83,6 +142,11 @@ namespace FFT
}
bool GetFFT( float * _samples )
{
if (!bCreated)
{
return false;
}
kiss_fft_cpx out[ FFT_SIZE + 1 ];