Skip to content

Commit

Permalink
Add OS/2 KAI audio driver
Browse files Browse the repository at this point in the history
  • Loading branch information
komh authored and derselbst committed Jul 27, 2024
1 parent 186a4af commit ecb0141
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 0 deletions.
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 */

0 comments on commit ecb0141

Please sign in to comment.