SyntaxBomb - Indie Coders

General Category => Worklogs => Topic started by: Midimaster on April 23, 2021, 14:12:00

Title: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on April 23, 2021, 14:12:00
I proudly present a new Audio-Interface for BlitzMax:
MiniAudio Audio-Library wrapper for BlitzMax NG

This interface will enable...


MiniAudio is a C-Library for various OS: Mac, Linux, Windows,... All informations and source code can be found here:

https://miniaud.io/index.html

For BlitzMax you need the mima.mod/miniaudio.mod-module, which you will find in the GitHub repository.

https://github.com/MidimasterSoft/BlitzMax-Miniaudio-Wrapper

The GitHub contains:
 - MiniAudioWrapper.c
 - MiniAudio.bmx
 - MiniAudioX.h
 - Documentation for BlitzMax help
 - A lot of code examples

In the example you will also find sample audio files for testing.

This is Version 1.25 from 2021-06-08.

In this topic you will find a manual and learn how to use the library.

This are the functions which are already working:




content of the GitHub:

MiniAudio.bmx
the BlitzMax-Part of the wrapper. Shows all avaiable functions


MiniAudioWrapper.c
the C-Part of the wrapper. Do not change anything.

MiniAudioX.h
the library. Do not change anything.

OpenClose.bmx
First demo app. Opens the device for playback and shows some informations, then close it immediately.


PlayNoise.bmx
Second demo app. Produces noise only when the mouse is pressed.


MiniAudioTestLatency.bmx
Enables you to recognize the latency of the device. Listen to the time delay between the rhythmic crackl and your mouse click


StereoSinus
Demonstrates how to create Samples in Realtime. Uses STEREO to create two different waveforms.


FreeAudioMove.bmx
(including Test.ABC.ogg)
Demonstrates how to simply playback an existing Audiofile. Uses 16bit-MONO and 12kHz and standard unsigned SHORTs.


Reverb.bmx
(including Test.ABC.ogg)
Demonstrates how to manipulate an existing Audiofile in Realtime. Uses a 16bit-MONO file with 12kHz, but internal 32bit-signed-Int-Samples


CaptureRecording.bmx
(including Test.ABC.ogg)
Demonstrates how to capture an 16bit-MONO-INPUT device with 48kHz, save the samples to a TAudioSample. Also DUPLEX is activated to listen immediately to the incoming signal.


LoadMP3.bmx
(including Test.ABC.mp3)
Demonstrates how to open a MP3-file for TAudioSample and TSound, PlaySound.


ConvertAudioSample.bmx
(including Test.ABC.ogg)
Demonstrates how to convert a 16bit-Audio to a 32bit-float Audio-Format (values from -1.0 .. + 1.0).


SaveTAudioSample.bmx
(including Test.ABC.ogg)
Demonstrates how to save a  BlitzMax AudioSample to a WAV file. Works with MONO and STEREO, 8bit and 16bit and free SampleRate.


WriteWavFile.bmx
Demonstrates how to save any TBank content as a continously Audio-Stream to a WAV file. Works with 1-32 channels, 8bit and 16bit 32bit and 32bit-float and free SampleRate.



CaptureRecording_II.bmx
Demonstrates how to capture high quality STEREO IN with 48kHz and 32bit-FLOAT, and save the result to a WAV-file.


CaptureRecording_III.bmx
Demonstrates how select Hardware-Interface and capture 1-32 IN-channels of an USB-Audio-Interface with 48kHz, modifies the samples and reduce them to STEREO for immediately DUPLEX-monitoring on computer-speakers. At the end a 8-track audio file will be saved.


Installation
Copy the content of the GitHub into the MOD-folder of BlitzMax NG
The path will be mima.mod/miniaudio.mod
See the example PlayNoise.bmx to see how to use the library
Report here at Syntaxbomb, if you find bug or have questions.


Download

https://github.com/MidimasterSoft/BlitzMax-Miniaudio-Wrapper
Title: Manual MiniAudio-Wrapper for BlitzMax
Post by: Midimaster on April 23, 2021, 17:04:15
API of MiniAudio-Wrapper


Installation
You need to extract the mima.mod to the BlitzMax Mod-directory:


Miminum Code

The start-up needs 1-3 steps:

1. create an TMiniAudio-object
2  open a device type with parameters

Code: BlitzMax
  1. Global MiniAudio:TMiniAudio=New TMiniAudio
  2. MiniAudio.GetDevice( MiniAudio.PLAYBACK, Miniaudio.FORMAT_S16, 2, 48000, MyCallBack)
  3.  

You can  open the device for  4 different jobs:

PLAYBACK opens the default device for Audio-Out only.

CAPTURE opens the default In-device for recording only.

DUPLEX is CAPTURE and PLAYBACK at the same time. Here you can manipulate the incoming signal and immediately forward it to the speakers. Like a PlugIn.

LOOPBACK enables you to "capture the speakers". This is for recording game's or browser's audio

 
In the next step you have to decide your parameters

SampleFormat is one of the following:

FORMAT_U8
is the old 8bit audio format with poor quality

FORMAT_S16
is the common 16bit audio format of nearly all audio files and the default BlitzMax-Format. But be careful! BlitzMax only knows only unsigned SHORTs as variable types.

FORMAT_S24
is a 24bit audio format, which is mainly used in prof Music-Equiment.

FORMAT_S32
is a 32bit audio format, which fits perfect to BlitzMax's INTEGER variable type.

FORMAT_F32
is the new Float-Format, which WASAPI uses intern and apps like AUDACITY too.

The possible number of Channels

... depent on your hardware. The number of channels must fit to your audio hardware. Normaly 2 is the best choice for STEREO or 1 for MONO. Higher values only if your device is able to handle.

The Hertz frequency
... is related to your audio file or audio device. But you can also choose any value between 8000 and 96000, which will have side effects. Typical values are: 44100 for CDs MP3s or 48000 for music studios.

As last parameter you tell the name of your callback -function

The Callback

You need a function where you can exchange samples with MiniAudio. This function is defined by you, but called from MiniAudio every 10msec. So keep your code inside to a minimum. Do no PRINT or DRAW... commands and do never END your app inside this callback. Tell this name of the callback as  4th parameter.


our Callback function MUST look like this:
Code: BlitzMax
  1. Function MyCallBack(a%, PlaybackBuffer:Short Ptr, RecordingBuffer:Short Ptr, Frames%)
  2.         ' do something with the samples
  3. End Function

a%
...is not used at the moment

Buffer:Short Ptr
...is the adress of the buffer where you send Samples to Audio-Out

RecordingBuffer:Short Ptr
...is the adress of the buffer where you find the capture samples.

Frames%
...tells you the number of frames that the buffer contains this time. Be careful! This may vary!!!

In the case of only PLAYBACK or CAPTURE the other buffer is not allowed to use!

You are allowed to change type of both pointers (independend) to fit to your needs and selected device typ:

Code: BlitzMax
  1. ... Buffer:Byte Ptr
  2. ... Buffer:Short Ptr
  3. ... Buffer:Int Ptr
  4. ... Buffer:Float Ptr
  5.  


Minimum Code: OpenClose.bmx
Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 800,600
  5. ' Setup of the device:
  6. Global MiniAudio:TMiniAudio=New TMiniAudio
  7. MiniAudio.GetDevice( MiniAudio.PLAYBACK, Miniaudio.FORMAT_S16, 2, 48000, MyCallBack)
  8.  
  9. MiniAudio.StartDevice()
  10. Repeat
  11.  
  12. Until AppTerminate()
  13. Miniaudio.KillDevice()
  14. End
  15.  
  16. Function MyCallBack(a:Byte Ptr, PlayBuffer:Short Ptr, RecordingBuffer:Short Ptr, Frames%)
  17.         ' do something with the samples
  18. End Function
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording
Post by: Midimaster on April 24, 2021, 02:32:59
How to send Samples to Miniaudio?

This is easy now. you only have to fill the Buffer in the Callback. MiniAudio calls your Callback-function every 10msec. This is the moment when you send the next datas to MiniAudio.


Sending nothing:

This is an allowed option. If you send nothing, but only return the function, MiniAudio will send SILENCE to the speaker:
Code: BlitzMax
  1. Function MyCallBack(a%, PlaybackBuffer:Short Ptr , RecordingBuffer:Short Ptr , Frames%)
  2.         ' do nothing causes silence
  3. End Function


Or you can send anything:

In this case random number, which will result in white noise:
Code: BlitzMax
  1. Function MyCallBack(a%, PlaybackBuffer:Short Ptr , RecordingBuffer:Short Ptr , Frames%)
  2.         ' here you manipulate the sound:
  3.         For Local i%=0 To frames-1
  4.                 PlaybackBuffer[i] = Rand(-32000, 32000)
  5.         Next
  6. End Function

The variable Frames% tells you how many frames you should send now. Be careful! This means not Samples, or Bytes, but Frames. A frame means 1 sample if MONO is selected or 2 samples if STEREO is choosen. Here is a table

it shows the avaiable FORMAT types and how long one frames is.
Code: [Select]
Format    Channels   Samples  Length  best pointer
--------------------------------------------------
FORMAT_U8   MONO        1       1     1 BYTE   
   "        STEREO      2       2     2 BYTEs

FORMAT_S16  MONO        1       2     1 SHORT 
   "        STEREO      2       4     2 SHORTs   
     
FORMAT_S24  MONO        1       3      ---     
   "        STEREO      2       6      ---   

FORMAT_S32  MONO        1       4     1 INT     
   "        STEREO      2       8     2 INTs   

FORMAT_F32  MONO        1       4     1 FLOAT       
   "        STEREO      2       8     2 FLOATs

This  means that in a FORMAT_U8   MONO you have to loop...
Code: BlitzMax
  1. Function MyCallBack(a%, Buffer:Byte Ptr , RecordingBuffer:Byte Ptr , Frames%)
  2.         For Local i%=0 To frames-1
  3.                 PlaybackBuffer[i]=Rand(255)
  4.         Next
  5.  
...to fill the buffer

but in  a FORMAT_S16 STEREO you have to loop...
Code: BlitzMax
  1. Function MyCallBack(a%, Buffer:SHORT Ptr , RecordingBuffer:Short Ptr , Frames%)
  2.         For Local i%=0 To frames-1
  3.                 PlaybackBuffer[2*i +0] = Rand(-32768, +32768)  ' LEFT
  4.                 PlaybackBuffer[2*i +1] = Rand(-32768, +32768)  ' RIGHT
  5.         Next
  6.  


Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording
Post by: Henri on April 26, 2021, 09:28:27
Hi Midimaster,

good work based on what I see. I always thought MiniAudio was a good candidate for wrapping for Blitzmax.

-Henri
Title: Open MP3 File
Post by: Midimaster on April 27, 2021, 08:15:52
Load MP3-Files

You also can open a MP3 file in BlitzMax with the MiniAudio-Library. The wrapper returns a TSound so you can directly play it with PlaySound():

Load_MP3.bmx
Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 400,200
  5.  
  6. ' Setup of the device:
  7. Global MiniAudio:TMiniAudio=New TMiniAudio
  8.  
  9. Local MySound:MiniAudio.LoadSound("TestABC.mp3")
  10. PlaySound MySound
  11.  
  12. Repeat
  13.         DrawText "Open and Play MP3 file",100,100
  14.         Flip
  15. Until AppTerminate()
  16. End
  17.  

(Code and Files in the ZIP-file at first post of this topic)


You also can open a MP3 file as a TAudioSample for manipualting the Samples. The wrapper returns a TAudioSample so you can indirectly play it with PlaySound():

LoadAudioSample_MP3.bmx
Code: BlitzMax
  1. SuperStrict
  2.  
  3. Import mima.miniaudio
  4. Graphics 400,200
  5.  
  6. ' Setup of the device:
  7. Global MiniAudio:TMiniAudio=New TMiniAudio
  8.  
  9. Local MySample:TAudioSample = MiniAudio.LoadAudioSample("TestABC.mp3")
  10. Local MySound:TSound=LoadSound(MySample)
  11. PlaySound MySound
  12.  
  13. Repeat
  14.         DrawText "Open and Play MP3 file",100,100
  15.         Flip
  16. Until AppTerminate()
  17. End
  18.  

(Code and Files in the ZIP-file at first post of this topic)
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: iWasAdam on April 29, 2021, 07:32:56
tested on a mac and it crashes at this point:
playnoise.bmx

Code: [Select]
' now start it:
'MiniAudio.StartDevice()
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on April 29, 2021, 08:29:18
*** DONE  ********************************
The problem iWasAdam descriped was related to the
BlitzMax Debug mode and could be solved with the version 1.18
*****************************************

Thank you for testing it on a MAC. This is really helpful, as the Windows versions looks like running perfect.

to keep the worklog free from long discussion I would like to move this to the related topic here:

"How to write a wrapper"


https://www.syntaxbomb.com/index.php/topic,8388.msg347049813.html#msg347049813
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on April 30, 2021, 09:36:32
Today I show a very interesting realtime manipulation:

Real Time Music Speed Changing

The algo is nearly the same like in the Reverb.Bmx example. A given Ogg.file will be manipulated before sending it to the speakers.

Today I have a standalone EXE for you. A narrator is telling anything and you can change his speed between -50% to +50%. The audio-file is included via incbin.

(https://www.syntaxbomb.com/index.php?action=dlattach;topic=8419.0;attach=4536;image)
Title: Convert TAudioSamples to new Audio-Frmats SignedInt32 or Float32
Post by: Midimaster on May 12, 2021, 13:59:39
This shows how to convert the old school BlitzMax audio format to modern formats, how WASAPI use it:

Convert Audio Formats

The MiniAudio-Wrapper enables to convert any audio format to any other format. For BlitzMax users is important to convert the mainly used 16bit signed SHORT format, because it is always mis-interpreted in BlitzMax. BlitzMax only knows unsigned SHORT. So the real values in audio files from -32767 to +32767 are show in Blitzmax as (wrong) values  0 upto 65535.

With the converter you can convert them to new 32bit-float which knows values from -1.00 to +1.00. and are used i all professional audio software.

Convert Frequencies

Also possible is now to convert any frequency into a new one. The algorithm selects optimized dithering for any conversion direction and any frequency values.

This example shows how to convert MONO-16bit-UNSIGNED-SHORT to MONO-32bit-FLOAT:

ConvertAudioSample.bmx
Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 800,600
  5.  
  6. ' Setup of the device:
  7. Global MiniAudio:TMiniAudio=New TMiniAudio
  8.  
  9. Local Source:TAudioSample=LoadAudioSample("TestABC.ogg")
  10.  
  11. Global ResultBank:TBank
  12. ResultBank= MiniAudio.ConvertAudioSample(Source, Miniaudio.FORMAT_F32, 1, 12000)
  13.  
  14. 'show 500 samples in old and new format:
  15.  
  16. For Local i%=1000 To 1500
  17.         Print  i + ".Sample  Source:" +  SoundBank.PeekShort(i*2) + "-->" + Resultbank.PeekFloat(i*4)
  18. Next
  19. End
  20.  
  21.  


 
Title: Re: MiniAudio-Wrapper for BlitzMax now as Module avaiable
Post by: Midimaster on May 12, 2021, 14:04:47
I converted the wrapper code to a module now.

Write...
Code: BlitzMax
  1. Import mima.miniaudio
to use it in your code.

I also added docs for use in the BitzMax Help. And you will find an example folder  in the mima.mod/miniaudio.mod  directory
Title: Now loading FLAC and WAV files with various bitrates
Post by: Midimaster on May 19, 2021, 08:33:35
Again an update for the MiniAudio-Wrapper:

Load FLAC files

You now can load audio files in *.FLAC format for playing it with PlaySound or load it into a TAudioSample(). This enables for the first time to load 24bit audio-files in BlitzMax. The TAudioSample will be converted automatically to SF_STEREO16LE or SF_MONO16LE.

Code: BlitzMax
  1. Import mima.miniaudio
  2.  
  3. ' Setup of the device:
  4. Global MiniAudio:TMiniAudio=New TMiniAudio
  5.  
  6. Local MySound:TSound = MiniAudio.LoadSound("TestABC.flac")
  7. PlaySound MySound
  8.  
  9. 'also possible:
  10. Local MySample:TAudioSample = MiniAudio.LoadAudioSample("TestABC.flac")
  11. Local MySound:TSound=LoadSound(MySample)
  12. PlaySound MySound
  13.  


Load WAV files

You now can load audio files in *.WAV format with different format bejond SF_STEREO16LE for playing it with PlaySound or load it into a TAudioSample(). This enables for the first time to load 32bit audio-files in BlitzMax.

Miniaudio enables to load Wav-files also when they are in the 32bit-Integer-Format or  32bit-Float-Format.

The TAudioSample will be converted automatically to SF_STEREO16LE or SF_MONO16LE.


Code: BlitzMax
  1. Import mima.miniaudio
  2.  
  3. ' Setup of the device:
  4. Global MiniAudio:TMiniAudio=New TMiniAudio
  5.  
  6. Local MySound:TSound = MiniAudio.LoadSound("TestABC.wav")
  7. PlaySound MySound
  8.  
  9. 'also possible:
  10. Local MySample:TAudioSample = MiniAudio.LoadAudioSample("TestABC.Wav")
  11. Local MySound:TSound=LoadSound(MySample)
  12. PlaySound MySound
  13.  

MiniAudio in DEBUG mode

With a modification of the miniaudio.h made by COL the Miniaudio Wrapper now runs stabil also in the BlitzMax DEBUG mode. Thanks a lot to COL for his support. The modified library is now named minaudiox.h and has 6 changes which you can find when searching for the keyword "BBThread"


Download

You will find the download of the last version of the wrapper in post#1:
https://www.syntaxbomb.com/index.php/topic,8419.msg347049742.html#msg347049742




what is next?
the next step will be to select various hardware devices, f.e. USB-24bit-Audio-Devices, USB-Studio-Equipment.

Title: Capture USB Hardware Audio Devices ans Save 32track WAV files.
Post by: Midimaster on May 21, 2021, 15:25:22
new version 1.20 is online.

USB Hardware Capture

Now you can record upto 32 audio channels at the same time or playback upto 32 channels. This makes possible individual sounds for each speaker of an 7.1 systems or drive 24track mixing console for musicians. 
Code: BlitzMax
  1. ...
  2. ' Setup of the device:
  3. Const  HERTZ:Int = 48000
  4.  
  5. Global MiniAudio:TMiniAudio=New TMiniAudio
  6. Miniaudio.SelectDevices(0,1)
  7. MiniAudio.GetDevice_II( MiniAudio.DUPLEX, Miniaudio.FORMAT_S32, 2, Miniaudio.FORMAT_S32, 8, HERTZ, MyCallBack)
  8.  
  9.  
  10. Global Source:TAudioSample=CreateAudioSample( HERTZ*61,  HERTZ, SF_MONO16LE)  '60 seconds
  11. Global SoundBank:TBank=CreateStaticBank(Source.Samples, Source.Length)
  12.  
  13. Global WritePointer:Int
  14.  
  15. ....
  16. Repeat
  17.  
  18. Until...
  19.  
  20.  
  21. Function MyCallBack(a%, PlayBackBuffer:Int Ptr, RecordingBuffer:Int Ptr, Frames%)
  22.         For Local i%=0 To frames-1
  23.                 Local valueL%=RecordingBuffer[8*i]+RecordingBuffer[8*i+1]+RecordingBuffer[8*i+2]+RecordingBuffer[8*i+3]
  24.                 Local valueR%=RecordingBuffer[8*i+7]+RecordingBuffer[8*i+7]'+RecordingBuffer[8*i+6]+RecordingBuffer[8*i+7]
  25.                 PlayBackBuffer[2*i]= valueR
  26.                 PlayBackBuffer[2*i+1]=valueR
  27.                 SoundBank.PokeShort(WritePointer+2*i , valueR/65536)
  28.         Next
  29.     WritePointer = (WritePointer + 2*Frames) Mod (HERTZ*60)
  30. End Function
  31.  
  32.  


TAudioSample WAV Saving

Now you can simply save your TAudioSample as a WAV file. These BlitzMax audio-formats supported:SF_MONO8, SF_MONO16LE, SF_STEREO8, SF_STEREO16LE

Code: BlitzMax
  1. ' save_taudiosample.bmx
  2. SuperStrict
  3. Import mima.miniaudio
  4. ' Setup of the device:
  5. Global MiniAudio:TMiniAudio=New TMiniAudio
  6.  
  7. Global Sample:TAudioSample=LoadAudioSample("TestABC.ogg")
  8.  
  9. MiniAudio.SaveTAudioSample("TestABC.wav", Sample)
  10.  
  11. End
  12.  




Multitrack WAV Saving
but you can also  save multitrack captured samples or  save multitrack (1-32 channels) TBanks as WAV. All audio-formats supported. Also continous audio streams can be saved as WAV periodically:

Code: BlitzMax
  1. ' save_wav_file.bmx
  2. SuperStrict
  3. Import mima.miniaudio
  4. ' Setup of the device:
  5. Global MiniAudio:TMiniAudio=New TMiniAudio
  6.  
  7. Global Stream:MMStreamID= MiniAudio.OpenWavFile("test.wav" , Miniaudio.FORMAT_F32 , 3 , 44100 )
  8. Print "StreamID=" + Stream.Id
  9. Global mode%, time%, Part%
  10. While Part<10
  11.         If time < MilliSecs()
  12.                 time = MilliSecs() + 500
  13.                 Part=Part+1
  14.                 PartRecord
  15.                 Print "recording part no. " + Part
  16.         EndIf
  17.         Delay 100
  18. Wend
  19. MiniAudio.CloseWavFile(Stream )
  20. End
  21.  
  22. Function PartRecord()
  23.         mode = (mode+1) Mod 3 ' only for demonstration of 3 channels
  24.  
  25.         Local Bank:TBank=CreateBank(5000*4*3+12)    ' 5000samples * 32bit * 3tracks + safetybytes
  26.         Global FrameLength% = 4*3  ' 32bit*3tracks
  27.         For Local I%=0 To 4999
  28.                 Local pos:Int=i*FrameLength
  29.                 Local v#=Sin(i)/2
  30.                 Bank.PokeFloat(Pos+mode*4, v)
  31.         Next
  32.         MiniAudio.WriteWavFile(Stream, Bank, 5000)
  33. End Function
  34.  
  35.  

Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Scaremonger on May 23, 2021, 21:27:21
Hi,
This is an awesome piece of work.

Just tested it on Linux and it fails to load the module because of filename case sensitivity. If you rename the module filename from "MiniAudio.bmx" to "miniaudio.bmx" it works great.

Si...
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: iWasAdam on May 24, 2021, 07:58:13
Please link to the latest version in your posts - not point to another post where it becomes difficult to work out where to download :(

If it's now at version xxx
put a direct download to Vxxx :)
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: GW on May 24, 2021, 16:59:11
Tried the mod. The samples started playing though the speaker on one my monitors despite headphones. The lib needs to pick the default device, not the first enumerated one.
Title: New Version 1.25 and moved to GitHub
Post by: Midimaster on June 08, 2021, 14:56:08
There is a new update 1.25 of the miniaudio wrapper avaiable. You will find it here:

https://github.com/MidimasterSoft/BlitzMax-Miniaudio-Wrapper

Here are some of the new functions/features:

Here are three code examples related to capture:

Simply Capture into old BlitzMax TAudioSample
Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 400,300
  5.  
  6. ' Setup of the device:
  7. Const  HERTZ:Int = 48000
  8.  
  9. Global MiniAudio:TMiniAudio=New TMiniAudio
  10.  
  11. MiniAudio.OpenDevice( MiniAudio.DUPLEX, Miniaudio.FORMAT_S16, 1, HERTZ, MyCallBack)
  12.  
  13. ' we need a TaudioSample for storing the incoming samples and a SHORT PTR to handle them
  14. Global Recording:TAudioSample=CreateAudioSample( HERTZ*61,  HERTZ, SF_MONO16LE)  '60 seconds
  15. Global RecordingRam:Short Ptr = Recording.Samples
  16.  
  17. Global WritePointer:Int, RecordMode%, Audio:TChannel
  18. Local Music:TSound =LoadSound(Recording)
  19. Audio=PlaySound(Music)
  20.  
  21. SetClsColor 255,255,255
  22. Repeat
  23.     Cls
  24.                 DrawScreen
  25.                 If MouseHit(1)
  26.                         RecordMode=1-RecordMode
  27.                         If RecordMode=0
  28.                                 Print "PLAY"
  29.                                 MiniAudio.StopDevice()
  30.                                 Local Music:TSound =LoadSound(Recording)
  31.                                 Audio=PlaySound(music)
  32.                         Else
  33.                                 Print "RECORD"
  34.                                 ClearSample()
  35.                                 StopChannel Audio
  36.                                 WritePointer=0
  37.                                 MiniAudio.StartDevice()
  38.                         EndIf
  39.                 EndIf  
  40.     Flip 0
  41. Until AppTerminate()
  42. Miniaudio.CloseDevice()
  43.  
  44.  
  45. Function MyCallBack(a%, PlayBackBuffer:Short Ptr, RecordingBuffer:Short Ptr, Frames:Int)
  46.         ' cares about not to overrun the TAudioSample-size:
  47.         If WritePointer>HERTZ*60 Then WritePointer=0
  48.  
  49.         For Local i:Int=0 To frames-1
  50.                 ' fetch the sample:
  51.                 Local value:Short   = RecordingBuffer[i]
  52.                
  53.                 ' duplx it immediately:
  54.                 PlayBackBuffer[i] = value
  55.                
  56.                 'and transfer it to the TAudioSample:
  57.                 RecordingRAM[WritePointer+i] = value
  58.         Next
  59.     WritePointer = WritePointer + Frames
  60. End Function
  61.  
  62.  
  63. Function ClearSample()
  64.         For Local i:Int=0 To HERTZ*60
  65.                 RecordingRAM[i]=0
  66.         Next                           
  67. End Function
  68.  
  69. Function DrawScreen()
  70.         ...
  71. End Function


Stereo Capture with high quality 32bit-Float and save to WAV-file
Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 400,300
  5.  
  6. ' Setup of the device:
  7. Const    HERTZ:Int = 48000
  8. Const CHANNELS:Int = 2
  9.  
  10. Global MiniAudio:TMiniAudio=New TMiniAudio
  11.  
  12. Global Recording:ExTAudioSample = ExTAudioSample.Create(HERTZ*61,  HERTZ, MiniAudio.FORMAT_F32, CHANNELS)
  13. Print Recording.format
  14. Print Recording.Hertz
  15. Print Recording.channels
  16. MiniAudio.OpenDevice( MiniAudio.DUPLEX, Miniaudio.FORMAT_F32, CHANNELS, HERTZ, MyCallBack)
  17.  
  18.  
  19. Global WritePointer:Int, RecordMode%
  20. SetClsColor 255,255,255
  21. Repeat
  22.     Cls
  23.                 DrawScreen
  24.                 If MouseHit(1)
  25.                         RecordMode=1-RecordMode
  26.                         If RecordMode=0
  27.                                 Print "PLAY"
  28.                                 MiniAudio.StopDevice()
  29.                                 MiniAudio.SaveExTAudioSample "MySong.WAV", Recording
  30.                         Else
  31.                                 Print "RECORD"
  32.                                 Recording.Clear
  33.                                 WritePointer=0
  34.                                 MiniAudio.StartDevice()
  35.                         EndIf
  36.                 EndIf  
  37.     Flip 0
  38. Until AppTerminate()
  39. Miniaudio.CloseDevice()
  40. End
  41.  
  42.  
  43. Function MyCallBack(a%, PlayBackBuffer:Float Ptr, RecordingBuffer:Float Ptr, Frames%)
  44.         ' cares about not to overrun the ExTAudioSample-size:
  45.         If WritePointer>HERTZ*60 Then WritePointer=0
  46.  
  47.         For Local i:Int=0 To frames-1
  48.                 ' fetch the sample:
  49.                 Local value:Float   = RecordingBuffer[i]
  50.                
  51.                 ' duplx it immediately:
  52.                 PlayBackBuffer[i] = value
  53.                
  54.                 'and transfer it to the TAudioSample:
  55.                 Recording.SampleFloat[WritePointer+i] = value
  56.         Next
  57.     WritePointer = WritePointer + Frames
  58.  
  59. End Function
  60.  
  61.  
  62.  
  63.  
  64. Function DrawDrawScreen()
  65. ...
  66. End Function
  67.  


8-Channel Capture from USB-hardware device and save as 8track-file
Code: BlitzMax
  1. ' example to demonstrate MULTI-CHANNEL capturing audio with miniaudio
  2. ' and transfering datas to the NEW extended ExTAudioSample type
  3. ' Quality is FORMAT_S32 only for demonstration
  4. ' the DUPLEX will reduce the 8 channels to 2 "manually"
  5. ' when recording is stopped the ExTAudioSample is saved as a 8track-16bit WAV-file
  6. ' this make it necessary to convert from S32 to S16
  7. SuperStrict
  8. Import mima.miniaudio
  9.  
  10. Graphics 400,300
  11.  
  12. ' Setup of the device:
  13. Const    HERTZ:Int = 44100
  14. Const CHANNELS:Int = 8
  15.  
  16. Global MiniAudio:TMiniAudio=New TMiniAudio
  17.  
  18. 'only hardware devices can capture 8 channels. So connect your USB-device and select it with its ID:
  19. Print   "Capture-Devices:"
  20. Local i:Int
  21. For Local DeviceName:String= EachIn MiniAudio.CaptureDevices()
  22.         Print  "ID=" + i + ": " + DeviceName
  23.         i=i+1
  24. Next
  25. Local MyUsbDevice:Int=1
  26. Miniaudio.SelectDevices(-1,MyUsbDevice)
  27.  
  28.  
  29. Global Recording:ExTAudioSample = ExTAudioSample.Create(HERTZ*61,  HERTZ, MiniAudio.FORMAT_S32, CHANNELS)
  30. Print Recording.format
  31. Print Recording.Hertz
  32. Print Recording.channels
  33. ' use OpenDevice_II when Playback and Capture needs different parameters:
  34. MiniAudio.OpenDevice_II( MiniAudio.DUPLEX, Miniaudio.FORMAT_S32, 2, Miniaudio.FORMAT_S32, CHANNELS, HERTZ, MyCallBack)
  35.  
  36.  
  37. Global WritePointer:Int
  38. Global RecordMode%
  39.  
  40. SetClsColor 255,255,255
  41. Repeat
  42.     Cls
  43.                 DrawScreen
  44.                 If MouseHit(1)
  45.                         RecordMode=1-RecordMode
  46.                         If RecordMode=0
  47.                                 Print "PLAY"
  48.                                 MiniAudio.StopDevice()
  49.                                 'this would easily save the wav with 32bit-INT:
  50.                                 MiniAudio.SaveExTAudioSample "MySong.WAV", Recording
  51.                                
  52.                                 ' but we can also change the format during saving:
  53.                                 Local StreamID:MMStreamID = MiniAudio.OpenWavFile("My16bitsong.Wav" , Miniaudio.FORMAT_S16, CHANNELS, HERTZ)
  54.                                 MiniAudio.WriteWavFile StreamID, Recording.SampleInt, Recording.Frames, Recording.Format, CHANNELS, HERTZ
  55.                                 MiniAudio.CloseWavfile StreamID
  56.                         Else
  57.                                 Print "RECORD"
  58.                                 Recording.Clear
  59.                                 WritePointer=0
  60.                                 MiniAudio.StartDevice()
  61.                         EndIf
  62.                 EndIf  
  63.     Flip 0
  64. Until AppTerminate()
  65. Miniaudio.CloseDevice()
  66. End
  67.  
  68.  
  69. Function MyCallBack(a%, PlayBackBuffer:Int Ptr, RecordingBuffer:Int Ptr, Frames:Int)
  70.         If WritePointer > (HERTZ*60*CHANNELS) Then WritePointer=0
  71.  
  72.         For Local i:Int=0 To Frames-1
  73.                 For Local j:Int=0 To CHANNELS-1
  74.                         ' fetch the samples:
  75.                         Local value:Int = RecordingBuffer[i*CHANNELS + j]
  76.                        
  77.                         'and transfer it to the TAudioSample:
  78.                         Recording.SampleInt[WritePointer+i*CHANNELS + j] = value               
  79.                 Next
  80.                 ' now route the 8 capture channels to only 2 playbak channels as you like:
  81.                 ' to prevent Distortion we divide each sample volume by 2
  82.                 Local valueL:Int = RecordingBuffer[8*i+0]/2 + RecordingBuffer[8*i+1]/2 + RecordingBuffer[8*i+2]/2 + RecordingBuffer[8*i+3]/2
  83.                 Local valueR:Int = RecordingBuffer[8*i+4]/2 + RecordingBuffer[8*i+5]/2 + RecordingBuffer[8*i+6]/2 + RecordingBuffer[8*i+7]/2
  84.                 PlayBackBuffer[2*i+0] = valueL
  85.                 PlayBackBuffer[2*i+1] = valueR
  86.         Next
  87.     WritePointer = WritePointer + Frames*CHANNELS
  88. End Function
  89.  
  90.  
  91. Function DrawScreen()
  92.         ...
  93. End Function
  94.  

Full example code can be downloaded form the GitHub repository!
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Baggey on July 03, 2021, 10:46:19
Absolutly awsome!

Got some more time to play with the sound side of my spectrum emulator

Ive down loaded mima.mod and extracted to  C:/Blitzmax/mod

when i try C:\BlitzMax\mod\mima.mod\miniaudio.mod\examples\PlayNoise.bmx

I am using Windows 10 and Blitzmax 1.5 I think it's called Vanilla

Code: BlitzMax
  1. SuperStrict
  2. Import mima.miniaudio
  3.  
  4. Graphics 800,600
  5.  
  6. ' Setup of the device:
  7. Global MiniAudio:TMiniAudio=New TMiniAudio
  8. MiniAudio.OpenDevice( MiniAudio.PLAYBACK, Miniaudio.FORMAT_S16, 1, 48000, MyCallBack)
  9.  
  10.  
  11.  
  12. ' now start it:
  13. MiniAudio.StartDevice()
  14. Global NOISE%=0, Zeit%=MilliSecs()
  15. Repeat
  16.         Cls
  17.         DrawText "Kick LEFT MOUSE for NOISE",100,100
  18.         If MouseDown(1)
  19.                         NOISE=1
  20.         Else
  21.                 NOISE=0
  22.         EndIf
  23.         Flip 0
  24. Until AppTerminate()
  25. Miniaudio.CloseDevice()
  26. End
  27.  
  28.  
  29. Function MyCallBack(a%, PlayBuffer:Short Ptr, RecordingBuffer:Short Ptr, Frames%)
  30.         ' here you manipulate the sound:
  31.         If NOISE=1
  32.                 For Local i%=0 To frames-1
  33.                         PlayBuffer[i]=Rand(-32000,+32000)
  34.                 Next
  35.         EndIf
  36. End Function

Im getting Compile Error Can't find interface for module 'mima.miniaudio'

(http://)

 :-[

Kind Regards Baggey
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Baggey on July 03, 2021, 11:29:19
So Ive tried in,

Blitzmax 1.5 ' It Dosent Work!  :'(

Works in Blitzmax NG  Thou? :-X

Any idea Why this dosent work in Blitzmax 1.5 or do the files need to be put into different places.

Kind regards Baggey
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on July 03, 2021, 11:53:41
Did you already build the modules?
What were the complate error mesages you received?


Also Hardcoal had problems using it with BlitzMax 1.50. Did you find his post already?
https://www.syntaxbomb.com/index.php/topic,8467.msg347050348.html#msg347050348

We could change some code lines to make it more compatible to BlitzMAX 1.50 too. But afterwards Hardcoal reported more issues and canceled futher testings.

We think the problems now are related to the reduced multi-thread-capabilities of old BlitzMax.
See this answer from Col:
https://www.syntaxbomb.com/index.php/topic,8467.msg347050389.html#msg347050389

Maybe he can write something here?
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Baggey on July 03, 2021, 12:06:25
My error messages are from the Output window! I don't know how to get a more detailed Log?

(http://)

Kind Regards Baggey
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Hardcoal on August 06, 2021, 09:36:27
i tried to compile the  mima.miniaudio and it didnt work..

im using blitzmax vanilla

it gives me this error

Code: [Select]
►mima.miniaudio was scheduled to next iteration
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s: Assembler messages:
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:2: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:3683: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:93856: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:93857: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:93858: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:96818: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:97458: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:97672: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:98312: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:98408: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:99048: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:99144: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:99784: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:99880: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:100520: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:108021: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:108661: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:108757: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:109397: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:109493: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:110133: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:110229: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:110869: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:112495: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:113135: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:115440: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:116049: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:122339: Error: no such instruction: `lzcntl %eax,%eax'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:148911: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:166658: Error: junk at end of line, first unrecognized character is `,'
C:\Users\Hardc\AppData\Local\Temp\ccpKnT8e.s:166805: Error: junk at end of line, first unrecognized character is `,'
Build Error: failed to compile D:/PORTABLE/BlitzMax/mod/mima.mod/miniaudio.mod/miniaudiowrapper.c
►►►►mima.miniaudio was not built. See error information on latest attempt.
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on August 06, 2021, 10:18:11
i tried to compile the  mima.miniaudio and it didnt work..

im using blitzmax vanilla


Sorry MiniAudio is for BlitzMax NG only. We tried to convert, but there a re too many problems. Maybe in the far future...

Problems are:
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Derron on August 06, 2021, 10:55:56
Blitzmax vanilla compiles C stuff with GCC - hence the required MinGW installation (or a copy - if you use NGs BMK, which finds MinGW inside MinGW32 or MinGWx86 ...)

BlitzMax vanilla has threaded support - but requires you do do a threaded build while NG defaults to threaded builds.
Nonetheless the "buffer refill threads" could be kicked off from threads written in C.

For an example check these codes:
https://github.com/TVTower/TVTower/blob/master/source/Dig/base.sfx.soundmanager.freeaudio.bmx
https://github.com/TVTower/TVTower/blob/master/source/Dig/base.sfx.soundmanager.freeaudio.c

In essence you have the C code run your thread and on "tick" it calls back into the (non threaded built) blitzmax vanilla part.


bye
Ron
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Midimaster on August 06, 2021, 11:13:22
@derron

I can send you a list of problem I had when comping it with BlitzMax 1.50.

some of the problems I could already solve with compiler branches. But the list is still long, and always new message appear if old problems are solved.



Maybe we succedd in getting it run on BlitzMax 1.50 too...
Title: Re: MiniAudio-Wrapper for BlitzMax enables WASAPI Playback and Recording + MP3
Post by: Hardcoal on August 07, 2021, 00:47:41
Its ok..

I dont expect people to convert things just for me lol..

ill manage somehow..

in the case of turning MP3 into wave ill just make something on NG and call it from BM 1.50
SimplePortal 2.3.6 © 2008-2014, SimplePortal