Expose more MiniAudio-Functions

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Expose more MiniAudio-Functions

Post by jamirokwai »

HI Fred,

after reading the docs of Miniaudio, I'd like to propose some more things:

- expose the MP3-decoder to use it with UseMP3Decoder()
- expose the generation functions for sine, etc
- expose the functions for effects and such
- expose the possibilities of the ring buffer

These four things would heavily increase the functionality of sound in PureBasic!

Alongside, I'd like to propose a new Audio-Decoder, based on the QOA-format (https://qoaformat.org). Infratec already did a great job adding the format to PureBasic (https://www.purebasic.fr/english/viewtopic.php?t=81865), but native functions would be great :-)
Regards,
JamiroKwai
User avatar
Mijikai
Addict
Addict
Posts: 1517
Joined: Sun Sep 11, 2016 2:17 pm

Re: Expose more MiniAudio-Functions

Post by Mijikai »

+1
Quin
Addict
Addict
Posts: 1124
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: Expose more MiniAudio-Functions

Post by Quin »

Massive +1. I would also really like to see recording, even supporting WASAPI loopback on Windows.
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

I've done a bit of porting with infratec and added partial a partial ma_device struct which is needed for a lot of functions, I don't think we need the whole structure though since its mostly for internal use.
There's still quite a bit to do but I think the hard parts done well maybe depends if there's any more structure returns to work around.

test copies input to output
Enums devices
can people test with pb6.10b6 on linux, osx,
compile as console

Code: Select all

Enumeration ma_device_type
  #ma_device_type_playback = 1
  #ma_device_type_capture  = 2
  #ma_device_type_duplex   = #ma_device_type_playback | #ma_device_type_capture ; 3
  #ma_device_type_loopback = 4
EndEnumeration
Macro ma_device_type : l : EndMacro

Enumeration ma_performance_profile
  #ma_performance_profile_low_latency
  #ma_performance_profile_conservative
EndEnumeration
Macro ma_performance_profile : l : EndMacro

Enumeration ma_format
  #ma_format_unknown = 0    ; Mainly used For indicating an error, but also used As the Default For the output format For decoders.
  #ma_format_u8      = 1
  #ma_format_s16     = 2    ; Seems To be the most widely supported format.
  #ma_format_s24     = 3    ; Tightly packed. 3 bytes per sample.
  #ma_format_s32     = 4
  #ma_format_f32     = 5
  #ma_format_count
EndEnumeration
Macro ma_format : l : EndMacro

Enumeration ma_resample_algorithm
  #ma_resample_algorithm_linear = 0 ; Fastest, lowest quality. Optional low-pass filtering. Default.
  #ma_resample_algorithm_custom
EndEnumeration
Macro ma_resample_algorithm : l : EndMacro

Enumeration ma_channel_mix_mode
  #ma_channel_mix_mode_rectangular = 0  ; Simple averaging based on the plane(s) the channel is sitting on.
  #ma_channel_mix_mode_simple           ; Drop excess channels; zeroed out extra channels.
  #ma_channel_mix_mode_custom_weights   ; Use custom weights specified in ma_channel_converter_config.
  #ma_channel_mix_mode_default = #ma_channel_mix_mode_rectangular
EndEnumeration
Macro ma_channel_mix_mode :  l : EndMacro

Enumeration ma_share_mode
  #ma_share_mode_shared = 0
  #ma_share_mode_exclusive
EndEnumeration
Macro ma_share_mode : l : EndMacro

Enumeration ma_wasapi_usage
  #ma_wasapi_usage_default = 0
  #ma_wasapi_usage_games
  #ma_wasapi_usage_pro_audio
EndEnumeration
Macro ma_wasapi_usage : l : EndMacro

Enumeration ma_opensl_stream_type
  #ma_opensl_stream_type_default = 0  ; Leaves the stream type unset.
  #ma_opensl_stream_type_voice        ; SL_ANDROID_STREAM_VOICE
  #ma_opensl_stream_type_system       ; SL_ANDROID_STREAM_SYSTEM
  #ma_opensl_stream_type_ring         ; SL_ANDROID_STREAM_RING
  #ma_opensl_stream_type_media        ; SL_ANDROID_STREAM_MEDIA
  #ma_opensl_stream_type_alarm        ; SL_ANDROID_STREAM_ALARM
  #ma_opensl_stream_type_notification ; SL_ANDROID_STREAM_NOTIFICATION
EndEnumeration
Macro ma_opensl_stream_type : l : EndMacro

Enumeration ma_opensl_recording_preset
  #ma_opensl_recording_preset_default = 0           ; Leaves the input preset unset.
  #ma_opensl_recording_preset_generic               ; SL_ANDROID_RECORDING_PRESET_GENERIC
  #ma_opensl_recording_preset_camcorder             ; SL_ANDROID_RECORDING_PRESET_CAMCORDER
  #ma_opensl_recording_preset_voice_recognition     ; SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION
  #ma_opensl_recording_preset_voice_communication   ; SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION
  #ma_opensl_recording_preset_voice_unprocessed     ; SL_ANDROID_RECORDING_PRESET_UNPROCESSED
EndEnumeration
Macro ma_opensl_recording_preset : l : EndMacro

Enumeration ma_aaudio_usage
  #ma_aaudio_usage_default = 0                    ; Leaves the usage type unset.
  #ma_aaudio_usage_media                          ; AAUDIO_USAGE_MEDIA
  #ma_aaudio_usage_voice_communication            ; AAUDIO_USAGE_VOICE_COMMUNICATION
  #ma_aaudio_usage_voice_communication_signalling ; AAUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING
  #ma_aaudio_usage_alarm                          ; AAUDIO_USAGE_ALARM
  #ma_aaudio_usage_notification                   ; AAUDIO_USAGE_NOTIFICATION
  #ma_aaudio_usage_notification_ringtone          ; AAUDIO_USAGE_NOTIFICATION_RINGTONE
  #ma_aaudio_usage_notification_event             ; AAUDIO_USAGE_NOTIFICATION_EVENT
  #ma_aaudio_usage_assistance_accessibility       ; AAUDIO_USAGE_ASSISTANCE_ACCESSIBILITY
  #ma_aaudio_usage_assistance_navigation_guidance ; AAUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
  #ma_aaudio_usage_assistance_sonification        ; AAUDIO_USAGE_ASSISTANCE_SONIFICATION
  #ma_aaudio_usage_game                           ; AAUDIO_USAGE_GAME
  #ma_aaudio_usage_assitant                       ; AAUDIO_USAGE_ASSISTANT
  #ma_aaudio_usage_emergency                      ; AAUDIO_SYSTEM_USAGE_EMERGENCY
  #ma_aaudio_usage_safety                         ; AAUDIO_SYSTEM_USAGE_SAFETY
  #ma_aaudio_usage_vehicle_status                 ; AAUDIO_SYSTEM_USAGE_VEHICLE_STATUS
  #ma_aaudio_usage_announcement                   ; AAUDIO_SYSTEM_USAGE_ANNOUNCEMENT
EndEnumeration
Macro ma_aaudio_usage : l : EndMacro

Enumeration ma_aaudio_content_type
  #ma_aaudio_content_type_default = 0             ; Leaves the content type unset.
  #ma_aaudio_content_type_speech                  ; AAUDIO_CONTENT_TYPE_SPEECH
  #ma_aaudio_content_type_music                   ; AAUDIO_CONTENT_TYPE_MUSIC
  #ma_aaudio_content_type_movie                   ; AAUDIO_CONTENT_TYPE_MOVIE
  #ma_aaudio_content_type_sonification            ; AAUDIO_CONTENT_TYPE_SONIFICATION
EndEnumeration
Macro ma_aaudio_content_type : l : EndMacro

Enumeration
  #ma_aaudio_input_preset_default = 0             ; Leaves the input preset unset.
  #ma_aaudio_input_preset_generic                 ; AAUDIO_INPUT_PRESET_GENERIC
  #ma_aaudio_input_preset_camcorder               ; AAUDIO_INPUT_PRESET_CAMCORDER
  #ma_aaudio_input_preset_voice_recognition       ; AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
  #ma_aaudio_input_preset_voice_communication     ; AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION
  #ma_aaudio_input_preset_unprocessed             ; AAUDIO_INPUT_PRESET_UNPROCESSED
  #ma_aaudio_input_preset_voice_performance       ; AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE
EndEnumeration
Macro ma_aaudio_input_preset : l : EndMacro

Enumeration ma_aaudio_allowed_capture_policy
  #ma_aaudio_allow_capture_default = 0            ; Leaves the allowed capture policy unset.
  #ma_aaudio_allow_capture_by_all                 ; AAUDIO_ALLOW_CAPTURE_BY_ALL
  #ma_aaudio_allow_capture_by_system              ; AAUDIO_ALLOW_CAPTURE_BY_SYSTEM
  #ma_aaudio_allow_capture_by_none                ; AAUDIO_ALLOW_CAPTURE_BY_NONE
EndEnumeration
Macro ma_aaudio_allowed_capture_policy :  l : EndMacro

Enumeration ma_backend
  #ma_backend_wasapi
  #ma_backend_dsound
  #ma_backend_winmm
  #ma_backend_coreaudio
  #ma_backend_sndio
  #ma_backend_audio4
  #ma_backend_oss
  #ma_backend_pulseaudio
  #ma_backend_alsa
  #ma_backend_jack
  #ma_backend_aaudio
  #ma_backend_opensl
  #ma_backend_webaudio
  #ma_backend_custom;  /* <-- Custom backend, With callbacks defined by the context config. */
  #ma_backend_null  ;   /* <-- Must always be the last item. Lowest priority, And used As the terminator For backend Enumeration. */
EndEnumeration 
Macro ma_backend : l : EndMacro

Enumeration ma_thread_priority
  #ma_thread_priority_idle     = -5
  #ma_thread_priority_lowest   = -4
  #ma_thread_priority_low      = -3
  #ma_thread_priority_normal   = -2
  #ma_thread_priority_high     = -1
  #ma_thread_priority_highest  =  0
  #ma_thread_priority_realtime =  1
  #ma_thread_priority_default  =  0
EndEnumeration  
Macro ma_thread_priority : l : EndMacro


Macro ma_bool8 : a : EndMacro

Macro ma_bool32 : l : EndMacro

Macro ma_uint32 : l : EndMacro

#MA_SUCCESS =0
#MA_MAX_DEVICE_NAME_LENGTH = 255
#MA_MAX_CHANNELS = 254
#MA_MAX_LOG_CALLBACKS = 4

Macro AlignC 
  align #PB_Structure_AlignC 
EndMacro   

Structure linear_Structure
  lpfOrder.ma_uint32
EndStructure

Structure ma_resampler_config AlignC 
  format.ma_format                   ; Must be either ma_format_f32 or ma_format_s16.
  channels.ma_uint32
  sampleRateIn.ma_uint32
  sampleRateOut.ma_uint32
  algorithm.ma_resample_algorithm    ; When set To ma_resample_algorithm_custom, pBackendVTable will be used.
  *pBackendVTable
  *pBackendUserData
  linear.linear_Structure
EndStructure

Structure playback_Structure AlignC  
  *pDeviceID         
  format.ma_format   
  channels.ma_uint32 
  *pChannelMap       
  channelMixMode.ma_channel_mix_mode 
  calculateLFEFromSpatialChannels.ma_bool32
  shareMode.ma_share_mode 
EndStructure

Structure capture_Structure AlignC
  *pDeviceID
  format.ma_format
  channels.ma_uint32
  *pChannelMap
  channelMixMode.ma_channel_mix_mode
  calculateLFEFromSpatialChannels.ma_bool32
  shareMode.ma_share_mode
EndStructure

Structure wasapi_Structure AlignC  
  usage.ma_wasapi_usage;
  noAutoConvertSRC.ma_bool8         ; When set to true, disables the use of AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM.
  noDefaultQualitySRC.ma_bool8      ; When set to true, disables the use of AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY.
  noAutoStreamRouting.ma_bool8      ; Disables automatic stream routing.
  noHardwareOffloading.ma_bool8     ; Disables WASAPI's hardware offloading feature.
  loopbackProcessID.ma_uint32       ;        /* The process ID to include or exclude for loopback mode. Set to 0 to capture audio from all processes. Ignored when an explicit device ID is specified. */
  loopbackProcessExclude.ma_bool8   ;   
  
EndStructure

Structure alsa_Structure AlignC 
  noMMap.ma_bool32          ; Disables MMap mode.
  noAutoFormat.ma_bool32    ; Opens the ALSA device with SND_PCM_NO_AUTO_FORMAT.
  noAutoChannels.ma_bool32  ; Opens the ALSA device with SND_PCM_NO_AUTO_CHANNELS.
  noAutoResample.ma_bool32  ; Opens the ALSA device with SND_PCM_NO_AUTO_RESAMPLE.
EndStructure

Structure pulse_Structure AlignC
  *pStreamNamePlayback
  *pStreamNameCapture
EndStructure

Structure coreaudio_Structure AlignC
  allowNominalSampleRateChange.ma_bool32  ; Desktop only. When enabled, allows changing of the sample rate at the operating system level.
EndStructure

Structure opensl_Structure AlignC
  streamType.ma_opensl_stream_type
  recordingPreset.ma_opensl_recording_preset
  enableCompatibilityWorkarounds.ma_bool32;
EndStructure

Structure aaudio_Structure AlignC
  usage.ma_aaudio_usage
  contentType.ma_aaudio_content_type
  inputPreset.ma_aaudio_input_preset
  allowedCapturePolicy.ma_aaudio_allowed_capture_policy
  noAutoStartAfterReroute.ma_bool32
  enableCompatibilityWorkarounds.ma_bool32
EndStructure

Prototype ma_device_data_proc(*pDevice, *pOutput, *pInput, frameCount.ma_uint32)
Prototype ma_device_notification_proc(*pNotification)
Prototype ma_stop_proc(*pDevice)

Structure ma_device_config AlignC   
  deviceType.ma_device_type        
  sampleRate.ma_uint32             
  periodSizeInFrames.ma_uint32     
  periodSizeInMilliseconds.ma_uint32
  periods.ma_uint32                 
  performanceProfile.ma_performance_profile 
  noPreSilencedOutputBuffer.ma_bool8        ; When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to silence.
  noClip.ma_bool8                           ; When set to true, the contents of the output buffer passed into the data callback will not be clipped after returning. Only applies when the playback sample format is f32.
  noDisableDenormals.ma_bool8               ; Do not disable denormals when firing the data callback.
  noFixedSizedCallback.ma_bool8             ; Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks.
  *dataCallback.ma_device_data_proc         
  *notificationCallback.ma_device_notification_proc 
  *stopCallback.ma_stop_proc                        
  *pUserData                                        
  resampling.ma_resampler_config                    
  playback.playback_Structure                         
  capture.capture_Structure                           
  wasapi.wasapi_Structure                            
  alsa.alsa_Structure                               
  pulse.pulse_Structure                             
  coreaudio.coreaudio_Structure                     
  opensl.opensl_Structure                           
  aaudio.aaudio_Structure                           
EndStructure

Structure ma_device_resampling AlignC
  algorithm.ma_resample_algorithm
  *pBackendVTable
  *pBackendUserData
  linear.linear_Structure
EndStructure 

Structure ma_device_id_custom 
  StructureUnion 
    i.l;
    s.a[256];
    *p      ;
  EndStructureUnion;   
EndStructure   

Structure ma_device_id AlignC
  StructureUnion
    wasapi.u[64]       ;             /* WASAPI uses a wchar_t string for identification. */
    dsound.a[16]       ;             /* DirectSound uses a GUID for identification. */
    winmm.ma_uint32    ;             /* When creating a device, WinMM expects a Win32 UINT_PTR for device identification. In practice it's actually just a UINT. */
    alsa.a[256]        ;             /* ALSA uses a name string for identification. */
    pulse.a[256]       ;             /* PulseAudio uses a name string for identification. */
    jack.l             ;             /* JACK always uses default devices. */
    coreaudio.a[256]   ;             /* Core Audio uses a string for identification. */
    sndio.a[256]       ;             /* "snd/0", etc. */
    audio4.a[256]      ;             /* "/dev/audio", etc. */
    oss.a[64]          ;             /* "dev/dsp0", etc. "dev/dsp" for the default device. */
    aaudio.ma_uint32   ;             /* AAudio uses a 32-bit integer For identification. */
    opensl.ma_uint32   ;             /* OpenSL|ES uses a 32-bit unsigned integer for identification. */
    webaudio.a[32]     ;             /* Web Audio always uses default devices for now, but if this changes it'll be a GUID. */
    custom.ma_device_id_custom  
                       ;             /* The custom backend could be anything. Give them a few options. */
    nullbackend.l      ;             /* The null backend uses an integer for device IDs. */
  EndStructureUnion  
EndStructure       

Macro ma_channel :  a : EndMacro   

Macro ma_dither_mode :  l : EndMacro  

Macro ma_data_converter_execution_path : l : EndMacro   

Macro ma_channel_conversion_path : l : EndMacro

Macro ma_device_state : l : EndMacro 

Macro ma_uint64 : q : EndMacro  

Macro ma_mutex : i : EndMacro

Structure weights
  StructureUnion
    *float.float
    *s16.long
  EndStructureUnion 
EndStructure  

Structure ma_channel_converter AlignC;
  format.ma_format
  channelsIn.ma_uint32;
  channelsOut.ma_uint32;
  mixingMode.ma_channel_mix_mode;
  conversionPath.ma_channel_conversion_path
  *pChannelMapIn 
  *pChannelMapOut
  *pShuffleTable ; /* Indexed by output channel index. */
  weights.weights 
  *_pHeap
  _ownsHeap.l
EndStructure 

Structure ma_lpf AlignC
  format.ma_format
  channels.ma_uint32
  sampleRate.ma_uint32
  lpf1Count.ma_uint32 
  lpf2Count.ma_uint32 
  *ma_lpf1            
  *ma_lpf2            
  *_pHeap             
  _ownsHeap.ma_bool32 
EndStructure   

Structure ma_linear_resampler_config AlignC
  format.ma_format                         
  channels.ma_uint32                       
  sampleRateIn.ma_uint32                   
  sampleRateOut.ma_uint32                  
  lpfOrder.ma_uint32                       ;The low-pass filter order. Setting this to 0 will disable low-pass filtering. */
  lpfNyquistFactor.d                       ;0..1. Defaults to 1. 1 = Half the sampling frequency (Nyquist Frequency), 0.5 = Quarter the sampling frequency (half Nyquest Frequency), etc. */
EndStructure 

Structure ma_linear_resampler_x 
  StructureUnion 
    *float.float
    *s16.Unicode
  EndStructureUnion
EndStructure   

Structure ma_linear_resampler AlignC 
  
  config.ma_linear_resampler_config
  inAdvanceInt.ma_uint32
  inAdvanceFrac.ma_uint32
  inTimeInt.ma_uint32    
  inTimeFrac.ma_uint32   
  x0.ma_linear_resampler_x  
  x1.ma_linear_resampler_x  
  lpf.ma_lpf
  *_pHeap   
  _ownsHeap.ma_bool32
EndStructure 

Structure  ma_resampler AlignC
  *pBackend
  *pBackendVTable
  *pBackendUserData
  format.ma_format
  channels.ma_uint32
  sampleRateIn.ma_uint32
  sampleRateOut.ma_uint32
  state.ma_linear_resampler
  *_pHeap;
  _ownsHeap.ma_bool32;
EndStructure 

Structure ma_data_converter AlignC
  formatIn.ma_format
  formatOut.ma_format
  channelsIn.ma_uint32
  channelsOut.ma_uint32
  sampleRateIn.ma_uint32
  sampleRateOut.ma_uint32
  ditherMode.ma_dither_mode;
  executionPath.ma_data_converter_execution_path;The execution path the data converter will follow when processing. */
  channelConverter.ma_channel_converter         
  resampler.ma_resampler                        
  hasPreFormatConversion.ma_bool8               
  hasPostFormatConversion.ma_bool8              
  hasChannelConverter.ma_bool8                  
  hasResampler.ma_bool8                         
  isPassthrough.ma_bool8                        
  _ownsHeap.ma_bool8                            
  *_pHeap                                       
EndStructure 

Structure ma_device_playback AlignC
  *pid.ma_device_id                      ;Set to NULL if using default ID, otherwise set to the address of "id". */
  id.ma_device_id                        ;If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
  name.a[#MA_MAX_DEVICE_NAME_LENGTH + 1] ;Maybe temporary. Likely To be replaced With a query API. */
  shareMode.ma_share_mode                ;Set To whatever was passed in when the device was initialized. */
  format.ma_format                      
  channels.ma_uint32                    
  channelMap.ma_channel[#MA_MAX_CHANNELS]
  internalFormat.ma_format               
  internalChannels.ma_uint32             
  internalSampleRate.ma_uint32           
  internalChannelMap.ma_channel[#MA_MAX_CHANNELS]
  internalPeriodSizeInFrames.ma_uint32           
  internalPeriods.ma_uint32                      
  channelMixMode.ma_channel_mix_mode             
  calculateLFEFromSpatialChannels.ma_bool32
  converter.ma_data_converter                    
  *pIntermediaryBuffer                    ;For implementing fixed sized buffer callbacks. Will be null If using variable sized callbacks. */
  intermediaryBufferCap.ma_uint32                
  intermediaryBufferLen.ma_uint32         ;How many valid frames are sitting in the intermediary buffer. */
  *pInputCache                            ;In external format. Can be null. */
  inputCacheCap.ma_uint64                        
  inputCacheConsumed.ma_uint64                   
  inputCacheRemaining.ma_uint64                  
EndStructure                                

Structure ma_device_capture AlignC
  *pID.ma_device_id                       ;Set to NULL if using default ID, otherwise set to the address of "id". */
  id.ma_device_id                         ;If using an explicit device, will be set to a copy of the ID used for initialization. Otherwise cleared to 0. */
  name.a[#MA_MAX_DEVICE_NAME_LENGTH + 1]  ;Maybe temporary. Likely to be replaced with a query API. */
  sharemode.ma_share_mode                 ;Set to whatever was passed in when the device was initialized. */
  format.ma_format                      
  channels.ma_uint32                    
  channelMap.ma_channel[#MA_MAX_CHANNELS]
  internalFormat.ma_format               
  internalChannels.ma_uint32             
  internalSampleRate.ma_uint32           
  internalChannelMap.ma_channel[#MA_MAX_CHANNELS]
  internalPeriodSizeInFrames.ma_uint32           
  internalPeriods.ma_uint32                      
  channelMixMode.ma_channel_mix_mode             
  calculateLFEFromSpatialChannels.ma_bool32;
  converter.ma_data_converter                    
  *pIntermediaryBuffer                           ;For implementing fixed sized buffer callbacks. Will be null If using variable sized callbacks. */
  intermediaryBufferCap.ma_uint32                
  intermediaryBufferLen.ma_uint32                ;How many valid frames are sitting in the intermediary buffer. */
EndStructure                                     

PrototypeC onMalloc(sz.i,*puserdata)
PrototypeC onRealloc(*p,sz.i,*pUserData)
PrototypeC onFree(*p,*pUserData)

Structure ma_allocation_callbacks  
  *pUserData;
  *onMalloc.onMalloc
  *onRealloc.onRealloc
  *onfree.onfree 
EndStructure 

Structure ma_rb AlignC
  *pBuffer;                         
  subbufferSizeInBytes.ma_uint32  
  subbufferCount.ma_uint32          
  subbufferStrideInBytes.ma_uint32 
  encodedReadOffset.ma_uint32     ; Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
  encodedWriteOffset.ma_uint32    ; Most significant bit is the loop flag. Lower 31 bits contains the actual offset in bytes. Must be used atomically. */
  ownsBuffe.ma_bool8              ; Used to know whether or not miniaudio is responsible for free()-ing the buffer. */
  clearOnWriteAcquire.ma_bool8    ; When set, clears the acquired write buffer before returning from ma_rb_acquire_write(). */
  pad.u
  allocationCallbacks.ma_allocation_callbacks 
EndStructure

Structure ma_data_source_base
  *ma_data_source_vtable
  rangeBegInFrames.ma_uint64
  rangeEndInFrames.ma_uint64;              /* Set to -1 for unranged (default). */
  loopBegInFrames.ma_uint64 ;              /* Relative to rangeBegInFrames. */
  loopEndInFrames.ma_uint64 ;              /* Relative to rangeBegInFrames. Set to -1 for the end of the range. */
  *pCurrent                 ;              /* When non-NULL, the data source being initialized will act as a proxy and will route all operations to pCurrent. Used in conjunction with pNext/onGetNext for seamless chaining. */
  *pNext                    ;              /* When set to NULL, onGetNext will be used. */
  *onGetNext                ;              /* Will be used when pNext is NULL. If both are NULL, no next will be used. */
  islooping.ma_bool32       
EndStructure 

Structure ma_pcm_rb AlignC
  ds.ma_data_source_base
  rb.ma_rb
  format.ma_format
  channels.ma_uint32
  sampleRate.ma_uint32
EndStructure 

Structure ma_duplex_rb AlignC
  rb.ma_pcm_rb
EndStructure

Structure ma_device AlignC  
  *pContext;                 
  type.ma_device_type                   
  sampleRate.ma_uint32       
  state.ma_device_state                       ;/* The state of the device is variable And can change at any time on any thread. Must be used atomically. */
  *onData.ma_device_data_proc                 ;/* Set once at initialization time and should not be changed after. */
  *onNotification.ma_device_notification_proc ;/* Set once at initialization time and should not be changed after. */
  *onStop.ma_stop_proc                        ;/* DEPRECATED. Use the notification callback instead. Set once at initialization time and should not be changed after. */
  *pUserData                                  ;/* Application defined data. */
  startStopLock.i                             
  *wakeupEvent                                
  *startEvent                                 
  *stopEvent                                  
  *thread                                      
  workResult.l                                ;/* This is set by the worker thread after it's finished doing a job. */
  isOwnerOfContext.ma_bool8                   ;/* When set to true, uninitializing the device will also uninitialize the context. Set to true when NULL is passed into ma_device_init(). */
  noPreSilencedOutputBuffer.ma_bool8          
  noClip.ma_bool8                             
  noDisableDenormals.ma_bool8                 
  noFixedSizedCallback.ma_bool8                 
  masterVolumeFactor.f                        ;/* Linear 0..1. Can be read and written simultaneously by different threads. Must be used atomically. */
  duplexRB.ma_duplex_rb                       ;/* Intermediary buffer for duplex device on asynchronous backends. */
  resampling.ma_device_resampling              
  playback.ma_device_playback                    
  capture.ma_device_capture                   
  pad.a[160]                                  ;-might need adjusting or add the rest of the structure   
EndStructure  

PrototypeC ma_log_callback_proc(*pUserData,level.ma_uint32,*pMessage);

Structure ma_log_callback;
    *onlog.ma_log_callback_proc
    *pUserData;
EndStructure;

Structure ma_log
    callbacks.ma_log_callback[#MA_MAX_LOG_CALLBACKS];
    callbackCount.ma_uint32;
    allocationCallbacks.ma_allocation_callbacks   ;/* Need to store these persistently because ma_log_postv() might need to allocate a buffer on the heap. */
    lock.ma_mutex                                 ;/* For thread safety just to make it easier and safer for the logging implementation. */
EndStructure

Structure ma_device_info_dataFormats 
  format.ma_format;                    /* Sample format. If set To ma_format_unknown, all sample formats are supported. */
  channels.ma_uint32;                 /* If set to 0, all channels are supported. */
  sampleRate.ma_uint32;               /* If set to 0, all sample rates are supported. */
  flags.ma_uint32;   
EndStructure  

Structure ma_device_info;
    ;/* Basic info. This is the only information guaranteed To be filled in during device Enumeration. */
    id.ma_device_id;
    name.a[#MA_MAX_DEVICE_NAME_LENGTH + 1];   /* +1 for null terminator. */
    isDefault.ma_bool32
    nativeDataFormatCount.ma_uint32;
    nativeDataFormats.ma_device_info_dataFormats[64];  /* Not sure how big to make this. There can be *many* permutations for virtual devices which can support anything. */
EndStructure

Structure ma_device_info_Array 
  e.ma_device_info[0] 
EndStructure   

Structure  ma_context
    *callbacks.ma_backend_callbacks
    backend.ma_backend;                 /* DirectSound, ALSA, etc. */
    *pLog;
    log.ma_log   ; /* Only used if the log is owned by the context. The pLog member will be set to &log in this case. */
    threadPriority.ma_thread_priority
    threadStackSize.i;
    *pUserData;
    allocationCallbacks.ma_allocation_callbacks 
    deviceEnumLock.ma_mutex;            /* Used to make ma_context_get_devices() thread safe. */
    deviceInfoLock.ma_mutex;            /* Used to make ma_context_get_device_info() thread safe. */
    deviceInfoCapacity.ma_uint32;       /* Total capacity of pDeviceInfos. */
    playbackDeviceInfoCount.ma_uint32;
    captureDeviceInfoCount.ma_uint32;
    *pDeviceInfos.ma_device_info    ;       /* Playback devices first, then capture. */
    pad.a[16]
EndStructure

Procedure ma_device_config_init(deviceType)
  
  Protected *config.ma_device_config = AllocateMemory(SizeOf(ma_device_config))
  *config\deviceType = deviceType;
  
  *config\resampling\format = #ma_format_unknown 
  *config\resampling\algorithm =  #ma_resample_algorithm_linear
  *config\resampling\linear\lpfOrder = 4   
  
  ProcedureReturn *config;
  
EndProcedure 

;-Imports 
ImportC  "miniaudio.lib" 
  ma_device_init(*pContext,*config,*Device)
  ma_device_start(*Device);
  ma_device_uninit(*Device);
  ma_get_bytes_per_sample(format.ma_format)
  ma_context_init(*ma_backend,backendCount.ma_uint32,*config,*context.ma_context)
  ma_context_get_devices(*context, *pPlaybackDeviceInfos, *playbackDeviceCount, *pCaptureDeviceInfos, *captureDeviceCount)
  ma_context_uninit(*context);
EndImport 

CompilerIf #PB_Compiler_IsMainFile 
  
  ProcedureC data_callback(*Device.ma_device,*Output,*Input,frameCount.l)
    Protected amount 
    
    If frameCount  
      amount = framecount * (ma_get_bytes_per_sample(*Device\capture\format) * *Device\capture\channels)   
      PrintN("copy " + Str(amount))
      
      If amount <> 0  
        CopyMemory(*input,*Output,amount) 
      EndIf
      
    EndIf 
  EndProcedure 
  
  OpenConsole()
  
  Global result;
  Global *deviceConfig.ma_device_config
  Global device.ma_device  
  
  *deviceConfig = ma_device_config_init(#ma_device_type_duplex)
  *deviceConfig\capture\pDeviceID  = #Null                    
  *deviceConfig\capture\format     = #ma_format_s16           
  *deviceConfig\capture\channels   = 2                        
  *deviceConfig\capture\shareMode  = #ma_share_mode_shared    
  *deviceConfig\playback\pDeviceID = #Null                    
  *deviceConfig\playback\format    = #ma_format_s16           
  *deviceConfig\playback\channels  = 2                        
  *deviceConfig\dataCallback       = @data_callback()         
  
  result = ma_device_init(#Null,*deviceConfig,@device);
  
  Debug PeekS(@device\capture\name[0],-1,#PB_Ascii) 
  
  If result <> #MA_SUCCESS 
    MessageRequester("error","failed to config " + Hex(result))  
    FreeMemory(*deviceConfig) 
    End 
  EndIf 
  
  result = ma_device_start(@device);
  If result <> #MA_SUCCESS 
    MessageRequester("error","failed to start " + Hex(result))  
    FreeMemory(*deviceConfig) 
    End 
  EndIf   
    
  Delay(1000) 
    
  ma_device_uninit(@device);
  FreeMemory(*deviceConfig) 
  
  ;-test device enumeration 
  Global  context.ma_context;
  Global  *pPlaybackDeviceInfos.ma_device_info_Array;
  Global  playbackDeviceCount.ma_uint32;
  Global  *pCaptureDeviceInfos.ma_device_info_Array;
  Global  captureDeviceCount.ma_uint32;
  Global  iDevice.ma_uint32;
  
  If ma_context_init(#Null, 0, #Null, @context) <> #MA_SUCCESS
    PrintN("Failed to initialize context");
    End -2                                ;
  EndIf 
  
  result = ma_context_get_devices(@context, @*pPlaybackDeviceInfos, @playbackDeviceCount, @*pCaptureDeviceInfos, @captureDeviceCount);
  If result <> #MA_SUCCESS
    PrintN("Failed to retrieve device information");
    End -3                                         ;
  EndIf 
  
  PrintN("Playback Devices");
  For iDevice = 0 To  playbackDeviceCount-1
    PrintN("device " + Str(iDevice) + " " + PeekS(@*pPlaybackDeviceInfos\e[iDevice]\name,-1,#PB_Ascii))
  Next   
  
  PrintN("")
  
  PrintN("Capture Devices");
  For iDevice = 0 To captureDeviceCount-1 
    PrintN("device " + Str(iDevice) + " " + PeekS(@*pCaptureDeviceInfos\e[iDevice]\name,-1,#PB_Ascii))
  Next 
  
  ma_context_uninit(@context)
  
  Input();
  
CompilerEndIf 

jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Expose more MiniAudio-Functions

Post by jamirokwai »

Hi Idle and Infratec,

wow, great news!

I tried on a Mac M2 with PB 6.10 beta 6. This raised an error:

Code: Select all

clang: error: no such file or directory: 'miniaudio.lib'
Regards,
JamiroKwai
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

jamirokwai wrote: Tue Feb 27, 2024 8:41 am Hi Idle and Infratec,

wow, great news!

I tried on a Mac M2 with PB 6.10 beta 6. This raised an error:

Code: Select all

clang: error: no such file or directory: 'miniaudio.lib'
Could it be "miniaudio.a" instead of .lib?
jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Expose more MiniAudio-Functions

Post by jamirokwai »

I copied the libmpminiaudio.a, added the full path to it and tried again. Now PB throws this error

Code: Select all

ld: warning: ignoring duplicate libraries: '-lm', '-lpthread', '/Applications/PureBasic/PureBasic 6.04 arm.app/Contents/Resources/compilers/debugger.a', '/Applications/PureBasic/PureBasic 6.04 arm.app/Contents/Resources/compilers/objectmanager.a', '/Applications/PureBasic/PureBasic 6.04 arm.app/Contents/Resources/compilers/systembase.a', '2DDrawing.a', 'Array.a', 'Cipher.a', 'CipherMD5.a', 'Cocoa.a', 'Console.a', 'Date.a', 'Event.a', 'FileSystem.a', 'Gadget.a', 'Image.a', 'ImagePlugin.a', 'ImagePluginBMP.a', 'Internal.a', 'LinkedList.a', 'Map.a', 'Memory.a', 'Menu.a', 'Network.a', 'Requester.a', 'SimpleList.a', 'String.a', 'System.a', 'VectorDrawing.a', 'Window.a'
ld: Undefined symbols:
_AudioComponentFindNext, referenced from:
_ma_context_init__coreaudio in miniaudio.a[2](miniaudio.o)
_ma_context_init__coreaudio in miniaudio.a[2](miniaudio.o)
_AudioComponentInstanceDispose, referenced from:
_ma_context_init__coreaudio in miniaudio.a[2](miniaudio.o)
...
Does that help?

Edit: Full Path to the original is "/Applications/PureBasic/PureBasic 6.10 beta.app/Contents/Resources/purelibraries/macos/libraries/libpbminiaudio.a"
Regards,
JamiroKwai
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

Looks like the lib is missing the device Enumeration for coreaudio, I guess for playback you don't need to enumerate the output devices so maybe it's not included. Fred might be able to answer that when he has some time.

If you comment out the test device enumeration section does it work?

edit:
seems the pb lib doesn't include ma_sound_init_from_file or ma_sound_init_from_file_w
and I'm not sure if I can get the raw pointer for a loadsound so currently I can't use the engine effects.
LamptonWorm
New User
New User
Posts: 1
Joined: Sun May 26, 2024 11:06 am

Re: Expose more MiniAudio-Functions

Post by LamptonWorm »

This is great, thanks idle and infratec!
Is there another place to pick up the latest code or should I check back on this post every now and then?
For now I've got the above working fine on Windows and I'm able to play back sample data using the call back.
jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Expose more MiniAudio-Functions

Post by jamirokwai »

Hi Idle,

sorry for the loooooong delay. I just compiled the lib for macOS and tried it.
The code stalls on line 655

Code: Select all

result = ma_device_init(#Null,*deviceConfig,@device);
However, on first run, it asked for mic-permissions, so something worked!

(btw, if anybody is interested in compiling on macOS)

create miniaudio.c

Code: Select all

// miniaudio.c
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
call clang

Code: Select all

clang -shared -o libminiaudio.dylib -fPIC miniaudio.c

You can importc libminiaudio.dylib like idle showed before.

Edit: I had to add the full path to the dylib for PureBasic to find it.
Last edited by jamirokwai on Thu Oct 10, 2024 10:31 am, edited 2 times in total.
Regards,
JamiroKwai
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

My example isn't working windows anymore with PB 6.12 not sure why.
jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Expose more MiniAudio-Functions

Post by jamirokwai »

idle wrote: Mon Oct 07, 2024 12:20 am My example isn't working windows anymore with PB 6.12 not sure why.
Interestingly, I used 6.12 on macOS (ARM) and it worked like I described above.
Regards,
JamiroKwai
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

jamirokwai wrote: Tue Oct 08, 2024 11:57 am
idle wrote: Mon Oct 07, 2024 12:20 am My example isn't working windows anymore with PB 6.12 not sure why.
Interestingly, I used 6.12 on macOS (ARM) and it worked like I described above.
It worked after I changed the padding of ma_context to 410 bytes, but I don't know what changed in PB to effect it. The pad before was 16 bytes. I really think it would be much easier to make a wrapper in c than try to import it.
Fred
Administrator
Administrator
Posts: 18161
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Expose more MiniAudio-Functions

Post by Fred »

#PB_Structure_AlignC doesn't work ?
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Expose more MiniAudio-Functions

Post by idle »

Yes I had AlignC Macro.
I think the issue was that I had taken a short cut on porting the structure and there's a lot to import

The mp3 sound dlI i made in inline c with my #include hacks doesn't work since the change to lld-link. Not sure what the problem is, i think the import lib is broken

It was easy to do with inline c and my hacks but it's complicated you don't need a whole C compiler chain but you do need the specific c compiler headers to make it work, I used clang to compile rather than gcc and even then some compiler options differ between gcc and clang.
....

this worked on 6.10 with my tools

Code: Select all


!//gccflags -IC:\llvm-mingw-20211002-msvcrt-x86_64\lib\clang\13.0.0\include; 
!//#include "E:\idle\pbcex\examples\miniaudio\miniaudio.h";
!//useclang;

ImportC "miniaudiox64.lib" : EndImport 

Structure sound_ma 
  *sound 
  *delaynode
EndStructure    

ProcedureCDLL maSound_Init() 
  
  Protected *engine
  Protected sz 
  !v_sz = sizeof(ma_engine); 
  *engine= AllocateMemory(sz);
  !ma_result result;
  !result = ma_engine_init(NULL, p_engine);
  !if (result == MA_SUCCESS) {
  ProcedureReturn *engine
  !}  
  
EndProcedure 

ProcedureCDLL maSound_UnInit(*engine)
  
  If *engine
    !ma_engine_uninit(p_engine);
    *engine = 0 
  EndIf
  
EndProcedure  

ProcedureCDLL maSound_LastError()
  ProcedureReturn @err 
EndProcedure   

ProcedureCDLL maSound_Free(sound) 
  Protected *snd.sound_ma = sound 
  If sound 
    ! ma_sound_uninit(p_snd->f_sound);
    If *snd\delaynode 
      ! ma_delay_node_uninit(p_snd->f_delaynode, NULL);
    EndIf 
    FreeMemory(*snd)   
  EndIf   
EndProcedure  

ProcedureCDLL maSound_Load(*engine,file.s,delay.f=0.0,decay.f=0.0)
  
  If file <> "" 
    
    Protected *snd.sound_ma = AllocateMemory(SizeOf(sound_ma))   
    Protected sz 
    !v_sz = sizeof(ma_sound);
    Protected *sound = AllocateMemory(sz) 
    
    !ma_result result;
    
    ! ma_uint32 channels;
    ! ma_uint32 sampleRate;
    
    ! channels   = ma_engine_get_channels(p_engine);
    ! sampleRate = ma_engine_get_sample_rate(p_engine);
    
    If delay <> 0.0 
      
      ! ma_delay_node* g_delayNode = malloc(sizeof(ma_delay_node));   /* The echo effect is achieved using a delay node. */
      ! p_snd->f_delaynode = g_delayNode; 
      
      ! ma_delay_node_config delayNodeConfig;  
      ! delayNodeConfig = ma_delay_node_config_init(channels, sampleRate, (ma_uint32)(sampleRate * v_delay), v_decay);
      ! result = ma_delay_node_init(ma_engine_get_node_graph(p_engine), &delayNodeConfig, NULL, g_delayNode);
      ! if (result != MA_SUCCESS) {
      ;err = "Failed to initialize delay node."
      Goto error
      ! }
      ! 
      !  ma_node_attach_output_bus(g_delayNode, 0, ma_engine_get_endpoint(p_engine), 0);
      
      !  result = ma_sound_init_from_file_w(p_engine,v_file, 0, NULL, NULL, p_sound);
      !  if (result != MA_SUCCESS) {
      ;err = "Failed to initialize sound"
      Goto error
      !  }
    EndIf 
    
    If delay <> 0.0 
      ;   /* Connect the output of the sound To the input of the effect. */
      ! ma_node_attach_output_bus(p_sound, 0, g_delayNode, 0);
    Else 
      !  result = ma_sound_init_from_file_w(p_engine,v_file, 0, NULL, NULL, p_sound);
      !  if (result != MA_SUCCESS) {
      ;err = "Failed to initialize sound"
      Goto error
      !  }
    EndIf 
    
    !p_snd->f_sound = p_sound;
    
    ProcedureReturn *snd 
    
    error: 
    
    maSound_Free(*snd)
    
  EndIf 
  
EndProcedure 

ProcedureCDLL maSound_Play(sound) 
  Protected *snd.sound_ma = sound 
  If sound 
    ! ma_sound_start(p_snd->f_sound);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Stop(sound)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_stop(p_snd->f_sound);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Set_Volume(Sound,volume.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_volume(p_snd->f_sound,v_volume);
  EndIf 
EndProcedure  

ProcedureCDLL.f maSound_Get_Volume(Sound) 
  Protected *snd.sound_ma = sound 
  Protected vol.f 
  If sound 
    !v_vol = ma_sound_get_volume(p_snd->f_sound); 
  EndIf 
  ProcedureReturn vol 
EndProcedure 

ProcedureCDLL maSound_Set_Pan(Sound,pan.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_pan(p_snd->f_sound, v_pan);
  EndIf  
EndProcedure   

ProcedureCDLL.f maSound_Get_Pan(Sound)
  Protected *snd.sound_ma = sound 
  Protected pan.f 
  If sound 
    !v_pan = ma_sound_get_pan(p_snd->f_sound); 
  EndIf   
  ProcedureReturn pan 
EndProcedure 

ProcedureCDLL maSound_Set_Pan_Mode(Sound,panMode.l)
  Protected *snd.sound_ma = sound  
  If sound 
    !ma_sound_set_pan_mode(p_snd->f_sound,v_panmode);
  EndIf 
EndProcedure 

ProcedureCDLL maSound_Get_Pan_Mode(Sound)
  Protected *snd.sound_ma = sound
  Protected mode 
  If sound 
    !v_mode = ma_sound_get_pan_mode(p_snd->f_sound);
  EndIf 
  ProcedureReturn mode 
EndProcedure   

ProcedureCDLL maSound_Set_Pitch(Sound,pitch.f)
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_pitch(p_snd->f_sound,v_pitch);
  EndIf   
EndProcedure 

ProcedureCDLL.f maSound_Get_Pitch(Sound)
  Protected *snd.sound_ma = sound
  Protected pitch.f
  If sound 
    !v_pitch = ma_sound_get_pitch(p_snd->f_sound);
  EndIf   
  ProcedureReturn pitch 
EndProcedure 

ProcedureCDLL maSound_Set_Spatialization_Enabled(Sound,enabled.l)
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_spatialization_enabled(p_snd->f_sound,v_enabled);
  EndIf   
EndProcedure   

ProcedureCDLL maSound_Is_Spatialization_Enabled(Sound)
  Protected *snd.sound_ma = sound
  Protected enabled.l 
  If sound 
    !v_enabled = ma_sound_is_spatialization_enabled(p_snd->f_sound);
  EndIf   
  ProcedureReturn enabled   
EndProcedure   

ProcedureCDLL maSound_Set_Pinned_Listener_Index(Sound,listenerIndex.l) 
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_pinned_listener_index(p_snd->f_sound,v_listenerindex);
  EndIf   
EndProcedure   

ProcedureCDLL maSound_Get_Pinned_Listener_Index(Sound)
  Protected *snd.sound_ma = sound
  Protected index.l 
  If sound 
    !v_index = ma_sound_get_pinned_listener_index(p_snd->f_sound);
  EndIf 
  ProcedureReturn index 
EndProcedure 

ProcedureCDLL maSound_Get_Listener_Index(Sound)
  Protected *snd.sound_ma = sound
  Protected index.l 
  If sound 
    !v_index = ma_sound_get_listener_index(p_snd->f_sound);
  EndIf 
  ProcedureReturn index 
EndProcedure   

ProcedureCDLL maSound_Get_Direction_To_Listener(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound 
    !ma_vec3f relativePos; 
    !relativePos = ma_sound_get_direction_to_listener(p_snd->f_sound);  
    !p_vec3->f_x = relativePos.x;
    !p_vec3->f_y = relativePos.y;
    !p_vec3->f_z = relativePos.z;
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Set_Position(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_position(p_snd->f_sound,p_vec3->f_x,p_vec3->f_y,p_vec3->f_z);
  EndIf   
EndProcedure       

ProcedureCDLL maSound_Get_Position(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound  
    !ma_vec3f relativePos; 
    !relativePos = ma_sound_get_position(p_snd->f_sound);  
    !p_vec3->f_x = relativePos.x;
    !p_vec3->f_y = relativePos.y;
    !p_vec3->f_z = relativePos.z;
  EndIf   
EndProcedure

ProcedureCDLL maSound_Set_Direction(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_direction(p_snd->f_sound,p_vec3->f_x,p_vec3->f_y,p_vec3->f_z);
  EndIf 
EndProcedure 

ProcedureCDLL maSound_Get_Direction(Sound,*vec3.Vector3)
  Protected *snd.sound_ma = sound
  If sound  
    !ma_vec3f relativePos; 
    !relativePos = ma_sound_get_direction(p_snd->f_sound);  
    !p_vec3->f_x = relativePos.x;
    !p_vec3->f_y = relativePos.y;
    !p_vec3->f_z = relativePos.z;
  EndIf   
EndProcedure

ProcedureCDLL maSound_Set_Velocity(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_velocity(p_snd->f_sound,p_vec3->f_x,p_vec3->f_y,p_vec3->f_z);
  EndIf   
EndProcedure  

ProcedureCDLL maSound_Get_Velocity(Sound,*vec3.Vector3) 
  Protected *snd.sound_ma = sound
  If sound  
    !ma_vec3f relativePos; 
    !relativePos = ma_sound_get_velocity(p_snd->f_sound);  
    !p_vec3->f_x = relativePos.x;
    !p_vec3->f_y = relativePos.y;
    !p_vec3->f_z = relativePos.z;
  EndIf   
  
EndProcedure   

ProcedureCDLL maSound_Set_Attenuation_Model(Sound,attenuationModel.l)
  Protected *snd.sound_ma = sound 
  If sound  
    !ma_sound_set_attenuation_model(p_snd->f_sound,v_attenuationmodel);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Get_Attenuation_Model(Sound)
  Protected *snd.sound_ma = sound 
  Protected mod 
  If sound  
    !v_mod = ma_sound_get_attenuation_model(p_snd->f_sound); 
  EndIf 
  ProcedureReturn mod 
EndProcedure 

ProcedureCDLL maSound_Set_Positioning(Sound,positioning.l)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_positioning(p_snd->f_sound,v_positioning);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Get_Positioning(Sound) 
  Protected *snd.sound_ma = sound 
  Protected pos 
  If sound  
    !v_pos = ma_sound_get_positioning(p_snd->f_sound);
  EndIf  
  ProcedureReturn pos 
EndProcedure    

ProcedureCDLL maSound_Set_Rolloff(Sound,rolloff.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_rolloff(p_snd->f_sound,v_rolloff);
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Rolloff(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_rolloff(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Min_Gain(Sound,minGain.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_min_gain(p_snd->f_sound,v_mingain); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Min_Gain(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_min_gain(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Max_Gain(Sound,maxGain.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_max_gain(p_snd->f_sound,v_maxgain); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Max_Gain(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_max_gain(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Min_Distance(Sound,minDistance.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_min_distance(p_snd->f_sound,v_mindistance); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Min_Distance(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_min_distance(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Max_Distance(Sound,maxDistance.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_max_distance(p_snd->f_sound,v_maxdistance); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Max_Distance(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_max_distance(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL  maSound_Set_Cone(Sound,*vec3.Vector3)  ;float innerAngleInRadians, float outerAngleInRadians, float outerGain)
  Protected *snd.sound_ma = sound
  If sound 
    !ma_sound_set_cone(p_snd->f_sound,p_vec3->f_x,p_vec3->f_y,p_vec3->f_z);
  EndIf   
EndProcedure  

ProcedureCDLL maSound_Get_Cone(Sound,*vec3.Vector3); float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain)
  Protected *snd.sound_ma = sound
  If sound  
    !ma_vec3f pos; 
    !ma_sound_get_cone(p_snd->f_sound,&pos.x,&pos.y,&pos.z);  
    !p_vec3->f_x = pos.x;
    !p_vec3->f_y = pos.y;
    !p_vec3->f_z = pos.z;
  EndIf   
EndProcedure   

ProcedureCDLL maSound_Set_Doppler_Factor(Sound,dopplerFactor.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_doppler_factor(p_snd->f_sound,v_dopplerfactor); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Doppler_Factor(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_doppler_factor(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Directional_Attenuation_Factor(Sound,directionalAttenuationFactor.f)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_directional_attenuation_factor(p_snd->f_sound,v_directionalattenuationfactor); 
  EndIf 
EndProcedure   

ProcedureCDLL.f maSound_Get_Directional_Attenuation_Factor(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_directional_attenuation_factor(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Fade_In_Pcm_Frames(Sound,volumeBeg.f,volumeEnd.f,fadeLengthInFrames.q)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_fade_in_pcm_frames(p_snd->f_sound,v_volumebeg,v_volumeend,v_fadelengthinframes);
  EndIf 
EndProcedure    

ProcedureCDLL maSound_Set_Fade_In_Milliseconds(sound,volumeBegin.f,volumeEnd.f,fadeLengthInMilliseconds.q);
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_fade_in_milliseconds(p_snd->f_sound,v_volumebegin,v_volumeend,v_fadelengthinmilliseconds);
  EndIf  
EndProcedure  

ProcedureCDLL.f maSound_Get_Current_Fade_Volume(Sound)
  Protected *snd.sound_ma = sound 
  Protected rol.f 
  If sound 
    !v_rol = ma_sound_get_current_fade_volume(p_snd->f_sound); 
  EndIf 
  ProcedureReturn rol 
EndProcedure   

ProcedureCDLL maSound_Set_Start_Time_In_Pcm_Frames(Sound,absoluteGlobalTimeInFrames.q)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_start_time_in_pcm_frames(p_snd->f_sound,v_absoluteglobaltimeinframes);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Set_Start_Time_In_Milliseconds(Sound,absoluteGlobalTimeInMilliseconds.q) 
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_start_time_in_milliseconds(p_snd->f_sound,v_absoluteglobaltimeinmilliseconds);
  EndIf 
EndProcedure

ProcedureCDLL maSound_Set_Stop_Time_In_Pcm_Frames(Sound,absoluteGlobalTimeInFrames.q) 
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_stop_time_in_pcm_frames(p_snd->f_sound,v_absoluteglobaltimeinframes);
  EndIf 
EndProcedure 

ProcedureCDLL maSound_Set_Stop_Time_In_Milliseconds(Sound,absoluteGlobalTimeInMilliseconds.q)
  Protected *snd.sound_ma = sound 
  If sound 
    !ma_sound_set_stop_time_in_milliseconds(p_snd->f_sound,v_absoluteglobaltimeinmilliseconds);
  EndIf 
EndProcedure    

ProcedureCDLL maSound_Is_Playing(Sound)
  Protected *snd.sound_ma = sound 
  Protected ret.l
  If sound  
    !v_ret = ma_sound_is_playing(p_snd->f_sound);  
  EndIf 
  ProcedureReturn ret 
EndProcedure 

ProcedureCDLL.q maSound_Get_Time_In_Pcm_Frames(Sound)
  Protected *snd.sound_ma = sound 
  Protected ret.q
  If sound  
    !v_ret = ma_sound_get_time_in_pcm_frames(p_snd->f_sound);  
  EndIf 
  ProcedureReturn ret 
EndProcedure   

ProcedureCDLL maSound_Set_Looping(Sound,isLooping.l) 
  Protected *snd.sound_ma = sound 
  If sound  
    !ma_sound_set_looping(p_snd->f_sound,v_islooping);
  EndIf 
EndProcedure   

ProcedureCDLL maSound_Is_Looping(Sound)
  Protected *snd.sound_ma = sound 
  Protected ret.l
  If sound  
    !v_ret =ma_sound_is_looping(p_snd->f_sound);  
  EndIf 
  ProcedureReturn ret 
EndProcedure 

ProcedureCDLL maSound_At_End(Sound)
  Protected *snd.sound_ma = sound 
  Protected ret.l
  If sound  
    !v_ret =ma_sound_at_end(p_snd->f_sound);  
  EndIf 
  ProcedureReturn ret 
EndProcedure 

ProcedureCDLL maSound_Seek_To_Pcm_Frame(Sound,frameindex.q)
  Protected *snd.sound_ma = sound 
  Protected ret.l
  If sound  
    !v_ret = ma_sound_seek_to_pcm_frame(p_snd->f_sound,v_frameindex);
  EndIf 
  ProcedureReturn ret
EndProcedure     

ProcedureCDLL maSound_Get_Data_Format(Sound,*Format.long,*Channels.long,*SampleRate.long,*ChannelMap.long,channelMapCap.i)
  Protected *snd.sound_ma = sound 
  Protected ret.l
  If sound  
    !v_ret = ma_sound_get_data_format(p_snd->f_sound,&p_format,&p_channels,&p_samplerate,&p_channelmap,v_channelmapcap);    
  EndIf 
  ProcedureReturn ret  
EndProcedure

CompilerIf #PB_Compiler_IsMainFile 

#ma_positioning_absolute =0
#ma_positioning_relative = 1 
 
#ma_attenuation_model_none = 0          ;/* No distance attenuation And no spatialization. */
#ma_attenuation_model_inverse = 1       ;/* Equivalent To OpenAL's AL_INVERSE_DISTANCE_CLAMPED. */
#ma_attenuation_model_linear = 2        ;/* Linear attenuation. Equivalent To OpenAL's AL_LINEAR_DISTANCE_CLAMPED. */
#ma_attenuation_model_exponential = 3   

ImportC "miniaudiosound.lib" 
  ma_Init()
  ma_UnInit(engine)
  ma_LastError()
  ma_FreeSound(sound) 
  ma_LoadSound(engine,file.s,delay.f=0.0,decay.f=0.0)
  ma_PlaySound(sound) 
  ma_StopSound(sound)
  ma_Sound_Set_Volume(Sound,volume.f)
  ma_Sound_Get_Volume(Sound)
  ma_Sound_Set_Pan(Sound,pan.f)
  ma_sound_set_pan_mode(Sound,panMode.l)
  ma_sound_get_pan_mode(sound)
  ma_sound_set_pitch(Sound,pitch.f)
  ma_sound_get_pitch(Sound)
  ma_sound_set_spatialization_enabled(Sound,enabled.l)
  ma_sound_is_spatialization_enabled(Sound)
  ma_sound_set_pinned_listener_index(Sound,listenerIndex.l)
  ma_sound_get_pinned_listener_index(Sound)
  ma_sound_get_listener_index(Sound)
  ma_sound_get_direction_to_listener(Sound,*vec3.Vector3)
  ma_sound_set_position(Sound,*vec3.Vector3) 
  ma_sound_get_position(Sound,*vec3.Vector3)
  ma_sound_set_direction(Sound,*vec3.Vector3)
  ma_sound_get_direction(Sound,*vec3.Vector3)
  ma_sound_set_velocity(Sound,*vec3.Vector3) 
  ma_sound_get_velocity(Sound,*vec3.Vector3)
  ma_sound_set_attenuation_model(Sound,attenuationModel.l)
  ma_sound_get_attenuation_model(Sound)
  ma_sound_set_positioning(Sound,ma_positioning.l)
  ma_sound_get_positioning(Sound) 
  ma_sound_set_rolloff(Sound,rolloff.f)
  ma_sound_get_rolloff(Sound)
  ma_sound_set_min_gain(Sound,minGain.f)
  ma_sound_get_min_gain(Sound)
  ma_sound_set_max_gain(Sound,maxGain.f)
  ma_sound_get_max_gain(Sound)
  ma_sound_set_min_distance(Sound,minDistance.f)
  ma_sound_get_min_distance(Sound)
  ma_sound_set_max_distance(Sound,maxDistance.f)
  ma_sound_get_max_distance(Sound)
  ma_sound_set_cone(Sound,*vec.Vector3)  ;float innerAngleInRadians, float outerAngleInRadians, float outerGain
  ma_sound_get_cone(Sound,*vec.Vector3)  ; float* pInnerAngleInRadians, float* pOuterAngleInRadians, float* pOuterGain)
  ma_sound_set_doppler_factor(Sound,dopplerFactor.f)
  ma_sound_get_doppler_factor(Sound)
  ma_sound_set_directional_attenuation_factor(Sound,directionalAttenuationFactor.f)
  ma_sound_get_directional_attenuation_factor(Sound)
  ma_sound_set_fade_in_pcm_frames(Sound,volumeBeg.f,volumeEnd.f,fadeLengthInFrames.q)
  ma_sound_set_fade_in_milliseconds(sound,volumeBegin.f,volumeEnd.f,fadeLengthInMilliseconds.q)
  ma_sound_get_current_fade_volume(Sound)
  ma_sound_set_start_time_in_pcm_frames(Sound,absoluteGlobalTimeInFrames.q)
  ma_sound_set_start_time_in_milliseconds(Sound,absoluteGlobalTimeInMilliseconds.q)
  ma_sound_set_stop_time_in_pcm_frames(Sound,absoluteGlobalTimeInFrames.q)
  ma_sound_set_stop_time_in_milliseconds(Sound,absoluteGlobalTimeInMilliseconds.q)
  ma_sound_is_playing(Sound)
  ma_sound_get_time_in_pcm_frames(Sound)
  ma_sound_set_looping(Sound,isLooping.l)
  ma_sound_is_looping(Sound)
  ma_sound_at_end(Sound)
  ma_sound_seek_to_pcm_frame(Sound,frameindex.q)
  ma_sound_get_data_format(Sound,*Format.long,*Channels.long,*SampleRate.long,*ChannelMap.long,channelMapCap.i)
EndImport   

Global engine

engine = ma_init() 
If engine 
  
  OpenConsole()
  
  sound = ma_LoadSound(engine,"E:\idle\Music\motat.mp3",0.6,0.25) 
  If sound 
    ma_PlaySound(sound)
    
    PrintN("Press Enter to quit...");
    Input()
    
    ma_FreeSound(sound) 
    
  Else 
    PrintN(PeekS(@ma_lastError())) 
    PrintN("Press Enter to quit...");
    Input()
    
  EndIf 
  
  ma_uninit(@engine)
  
EndIf 

CompilerEndIf 

To make inline C usable for direct includes all that's required is to have #include outside of the scope of the main function and also a copy of the gcc include headers.
Post Reply