Expose more MiniAudio-Functions

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
jamirokwai
Enthusiast
Enthusiast
Posts: 772
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: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Expose more MiniAudio-Functions

Post by Mijikai »

+1
Quin
Enthusiast
Enthusiast
Posts: 319
Joined: Thu Mar 31, 2022 7:03 pm
Location: 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.
PB v5.40/6.10, Windows 10 64-bit.
16-core AMD Ryzen 9 5950X, 128 GB DDR5.
User avatar
idle
Always Here
Always Here
Posts: 5090
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: 772
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: 5090
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: 772
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: 5090
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.
Post Reply