Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OS/2 KAI audio driver #1332

Merged
merged 1 commit into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ endif ( CMAKE_SYSTEM MATCHES "Darwin" )

if ( CMAKE_SYSTEM MATCHES "OS2" )
option ( enable-dart "compile DART support (if it is available)" on )
option ( enable-kai "compile KAI support (if it is available)" on )
set ( enable-ipv6 off )
endif ( CMAKE_SYSTEM MATCHES "OS2" )

Expand Down Expand Up @@ -367,6 +368,9 @@ set ( LIBFLUID_LIBS ${MATH_LIBRARY} Threads::Threads )
unset ( DART_SUPPORT CACHE )
unset ( DART_LIBS CACHE )
unset ( DART_INCLUDE_DIRS CACHE )
unset ( KAI_SUPPORT CACHE )
unset ( KAI_LIBS CACHE )
unset ( KAI_INCLUDE_DIRS CACHE )
if ( CMAKE_SYSTEM MATCHES "OS2" )
set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Zbin-files" )
set ( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Zbin-files" )
Expand All @@ -375,6 +379,14 @@ if ( CMAKE_SYSTEM MATCHES "OS2" )
set ( DART_SUPPORT ${HAVE_DART_H} )
unset ( DART_INCLUDE_DIRS CACHE )
endif ( enable-dart )
if ( enable-kai )
check_include_files ( "kai.h" HAVE_KAI_H )
if ( HAVE_KAI_H )
set ( KAI_SUPPORT ${HAVE_KAI_H} )
set ( KAI_LIBS "-lkai" )
endif ( HAVE_KAI_H )
unset ( KAI_INCLUDE_DIRS CACHE )
endif ( enable-kai )
endif ( CMAKE_SYSTEM MATCHES "OS2" )

# Solaris / SunOS
Expand Down
1 change: 1 addition & 0 deletions FluidSynthConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(FLUIDSYNTH_SUPPORT_COREMIDI @COREMIDI_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_DART @DART_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_DSOUND @DSOUND_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_JACK @JACK_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_KAI @KAI_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_MIDISHARE @MIDISHARE_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_OBOE @OBOE_SUPPORT@)
set(FLUIDSYNTH_SUPPORT_OPENSLES @OPENSLES_SUPPORT@)
Expand Down
6 changes: 6 additions & 0 deletions cmake_admin/report.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ else ( DART_SUPPORT )
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} OS/2 DART: no\n" )
endif ( DART_SUPPORT )

if ( KAI_SUPPORT )
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} OS/2 KAI: yes\n" )
else ( KAI_SUPPORT )
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} OS/2 KAI: no\n" )
endif ( KAI_SUPPORT )

if ( OSS_SUPPORT )
set ( AUDIO_MIDI_REPORT "${AUDIO_MIDI_REPORT} OSS: yes\n" )
else ( OSS_SUPPORT )
Expand Down
10 changes: 10 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ if ( DART_SUPPORT )
set ( fluid_dart_SOURCES drivers/fluid_dart.c )
endif ( DART_SUPPORT )

if ( KAI_SUPPORT )
set ( fluid_kai_SOURCES drivers/fluid_kai.c )
endif ( KAI_SUPPORT )

if ( MIDISHARE_SUPPORT )
set ( fluid_midishare_SOURCES drivers/fluid_midishare.c )
endif ( MIDISHARE_SUPPORT )
Expand Down Expand Up @@ -232,6 +236,7 @@ add_library ( libfluidsynth-OBJ OBJECT
${fluid_dart_SOURCES}
${fluid_dbus_SOURCES}
${fluid_jack_SOURCES}
${fluid_kai_SOURCES}
${fluid_pipewire_SOURCES}
${fluid_midishare_SOURCES}
${fluid_opensles_SOURCES}
Expand Down Expand Up @@ -347,6 +352,7 @@ endif ( MACOSX_FRAMEWORK )
# but since they do not have a link step nothing is done with their object files.
target_link_libraries ( libfluidsynth-OBJ PUBLIC
${DART_LIBS}
${KAI_LIBS}
${COREAUDIO_LIBS}
${COREMIDI_LIBS}
${WINDOWS_LIBS}
Expand Down Expand Up @@ -414,6 +420,10 @@ if ( DART_SUPPORT )
target_include_directories ( libfluidsynth-OBJ PUBLIC ${DART_INCLUDE_DIRS} )
endif ( DART_SUPPORT )

if ( KAI_SUPPORT )
target_include_directories ( libfluidsynth-OBJ PUBLIC ${KAI_INCLUDE_DIRS} )
endif ( KAI_SUPPORT )

if ( MIDISHARE_SUPPORT )
target_link_libraries ( libfluidsynth-OBJ PUBLIC MidiShare::MidiShare )
endif ( MIDISHARE_SUPPORT )
Expand Down
3 changes: 3 additions & 0 deletions src/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@
/* Define to enable JACK driver */
#cmakedefine JACK_SUPPORT @JACK_SUPPORT@

/* Define to enable KAI driver */
#cmakedefine KAI_SUPPORT @KAI_SUPPORT@

/* Define to enable PipeWire driver */
#cmakedefine PIPEWIRE_SUPPORT @PIPEWIRE_SUPPORT@

Expand Down
10 changes: 10 additions & 0 deletions src/drivers/fluid_adriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ static const fluid_audriver_definition_t fluid_audio_drivers[] =
},
#endif

#if KAI_SUPPORT
{
"kai",
new_fluid_kai_audio_driver,
NULL,
delete_fluid_kai_audio_driver,
fluid_kai_audio_driver_settings
},
#endif

#if DART_SUPPORT
{
"dart",
Expand Down
7 changes: 7 additions & 0 deletions src/drivers/fluid_adriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ fluid_audio_driver_t *new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings,
void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p);
#endif

#if KAI_SUPPORT
fluid_audio_driver_t *new_fluid_kai_audio_driver(fluid_settings_t *settings,
fluid_synth_t *synth);
void delete_fluid_kai_audio_driver(fluid_audio_driver_t *p);
void fluid_kai_audio_driver_settings(fluid_settings_t *settings);
#endif

#if DART_SUPPORT
fluid_audio_driver_t *new_fluid_dart_audio_driver(fluid_settings_t *settings,
fluid_synth_t *synth);
Expand Down
164 changes: 164 additions & 0 deletions src/drivers/fluid_kai.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
* Copyright (C) 2024 KO Myung-Hun
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/

/* fluid_kai.c
*
* Driver for OS/2 KAI
*
*/

#include "fluid_adriver.h"
#include "fluid_settings.h"
#include "fluid_sys.h"

#if KAI_SUPPORT

#define INCL_DOS
#include <os2.h>

#include <kai.h>

#define NUM_MIX_BUFS 2

/** fluid_kai_audio_driver_t
*
* This structure should not be accessed directly. Use audio port
* functions instead.
*/
typedef struct {
fluid_audio_driver_t driver;
fluid_synth_t *synth;
int frame_size;
HKAI hkai; /* KAI handle */
} fluid_kai_audio_driver_t;

static APIRET APIENTRY
fluid_kai_callback(PVOID pCBData, PVOID pBuffer, ULONG ulSize);

/**************************************************************
*
* KAI audio driver
*
*/

void fluid_kai_audio_driver_settings(fluid_settings_t *settings)
{
fluid_settings_register_str(settings, "audio.kai.device", "default", 0);
}

fluid_audio_driver_t *
new_fluid_kai_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
{
fluid_kai_audio_driver_t *dev;
KAISPEC wanted, obtained;
double sample_rate;
int periods, period_size;
ULONG rc;

dev = FLUID_NEW(fluid_kai_audio_driver_t);
if (dev == NULL) {
FLUID_LOG(FLUID_ERR, "Out of memory");
return NULL;
}

FLUID_MEMSET(dev, 0, sizeof(fluid_kai_audio_driver_t));

fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
fluid_settings_getint(settings, "audio.periods", &periods);
fluid_settings_getint(settings, "audio.period-size", &period_size);

/* check the format */
if (!fluid_settings_str_equal(settings, "audio.sample-format", "16bits")) {
FLUID_LOG(FLUID_ERR, "Unhandled sample format");
goto error_recovery;
}

dev->synth = synth;
dev->frame_size = 2/* channels */ * sizeof(short)/* 16bits sample */;

/* Initialize KAI */
rc = kaiInit(KAIM_AUTO);
if (rc != KAIE_NO_ERROR) {
FLUID_LOG(FLUID_ERR, "Cannot initialize KAI, rc = %lu", rc);
goto error_recovery;
}

/* Open KAI */
wanted.usDeviceIndex = 0; /* default device */
wanted.ulType = KAIT_PLAY;
wanted.ulBitsPerSample = BPS_16; /* only 16bits audio */
wanted.ulSamplingRate = sample_rate;
wanted.ulDataFormat = MCI_WAVE_FORMAT_PCM;
wanted.ulChannels = 2; /* only 2 channels */
wanted.ulNumBuffers = NUM_MIX_BUFS;
wanted.ulBufferSize = periods * period_size * dev->frame_size;
wanted.fShareable = TRUE;
wanted.pfnCallBack = fluid_kai_callback;
wanted.pCallBackData = dev;

rc = kaiOpen(&wanted, &obtained, &dev->hkai);
if (rc != KAIE_NO_ERROR) {
FLUID_LOG(FLUID_ERR, "Cannot open KAI, rc = %lu", rc);
goto error_recovery;
}

/* Start to play */
kaiPlay(dev->hkai);

return (fluid_audio_driver_t *) dev;

error_recovery:

delete_fluid_kai_audio_driver((fluid_audio_driver_t *) dev);
return NULL;
}

void delete_fluid_kai_audio_driver(fluid_audio_driver_t *p)
{
fluid_kai_audio_driver_t *dev = (fluid_kai_audio_driver_t *) p;

fluid_return_if_fail(dev != NULL);

/* Stop playing */
kaiStop(dev->hkai);

/* Close KAI */
kaiClose(dev->hkai);

/* Terminate KAI */
kaiDone();

FLUID_FREE(dev);
}

static APIRET APIENTRY
fluid_kai_callback(PVOID pCBData, PVOID pBuffer, ULONG ulSize)
{
fluid_kai_audio_driver_t *dev = (fluid_kai_audio_driver_t *) pCBData;

FLUID_MEMSET(pBuffer, 0, ulSize);
fluid_synth_write_s16(dev->synth, ulSize / dev->frame_size,
pBuffer, 0, 2, pBuffer, 1, 2 );

return ulSize;
}

#endif /* #if KAI_SUPPORT */
Loading