It is currently Sun Dec 15, 2019 12:19 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: Audio Synthesis
PostPosted: Mon Feb 25, 2013 6:40 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
The code below creates a simple audio stream for audio synthesis.
What it does is already possible using PortAudio but this is a native approach not requiring anything else.

Include file
Code:
; AudioStream.pbi

#AUDIOBUFFER_SIZE = 16384
#AUDIOBUFFER_SAMPLES = #AUDIOBUFFER_SIZE >> 3

Structure AudioStreamBasicDescription
  mSampleRate.d
  mFormatID.l
  mFormatFlags.l
  mBytesPerPacket.l
  mFramesPerPacket.l
  mBytesPerFrame.l
  mChannelsPerFrame.l
  mBitsPerChannel.l
  mReserved.l
EndStructure

Structure AudioQueueBuffer
  mAudioDataBytesCapacity.i
  mAudioData.i
  mAudioDataByteSize.i
  mUserData.i
  mPacketDescriptionCapacity.i
  mPacketDescriptions.i
  mPacketDescriptionCount.i
EndStructure

Structure AudioStreamStereoSample
  l.f
  r.f
EndStructure

Structure AudioStreamSamples
  StructureUnion
    s.d[0]
    ss.AudioStreamStereoSample[0]
  EndStructureUnion
EndStructure

ImportC "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
  AudioQueueAllocateBuffer(inAQ, inBufferByteSize, *outBuffer)
  AudioQueueDispose(inAQ, inImmediate = #True)
  AudioQueueEnqueueBuffer(inAQ, inBuffer, inNumPacketDescs = 0, *inPacketDescs = #Null)
  AudioQueueNewOutput(*inFormat, inCallbackProc, *inUserData, inCallbackRunLoop, inCallbackRunLoopMode, inFlags, *outAQ)
  AudioQueueSetParameter(inAQ, inParamID, inValue.f)
  AudioQueueStart(inAQ, *inStartTime = #Null)
  AudioQueueStop(inAQ, inImmediate = #True)
EndImport

Prototype AudioStream_Callback_Proto(*SampleData.Float)
Global AudioStream_Callback.AudioStream_Callback_Proto

Global *AudioStream_Buf1.AudioQueueBuffer, *AudioStream_Buf2.AudioQueueBuffer
Global AudioStream_Queue = 0

ProcedureC AudioStream_Callback_(*ptr, queue, *buf.AudioQueueBuffer)
  AudioStream_Callback(*buf\mAudioData)
  AudioQueueEnqueueBuffer(queue, *buf)
EndProcedure

Procedure AudioStream_Init(*Callback, Stereo = #False)
  AudioStream_Callback = *Callback
  Protected fmt.AudioStreamBasicDescription
  fmt\mSampleRate = 44100
  fmt\mFormatID = $6C70636D; kAudioFormatLinearPCM
  fmt\mFormatFlags = 1; kAudioFormatFlagIsFloat
  fmt\mFramesPerPacket = 1
  fmt\mBytesPerFrame = 8
  fmt\mBytesPerPacket = 8
  If Stereo
    fmt\mChannelsPerFrame = 2
    fmt\mBitsPerChannel = 32
  Else
    fmt\mChannelsPerFrame = 1
    fmt\mBitsPerChannel = 64
  EndIf
  If AudioQueueNewOutput(@fmt, @AudioStream_Callback_(), #Null, #Null, #Null, 0, @AudioStream_Queue) = 0
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf1)
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf2)
    *AudioStream_Buf1\mAudioDataByteSize = #AUDIOBUFFER_SIZE
    *AudioStream_Buf2\mAudioDataByteSize = #AUDIOBUFFER_SIZE
  EndIf
EndProcedure

Procedure AudioStream_SetVolume(volume.f)
  If AudioStream_Queue
    AudioQueueSetParameter(AudioStream_Queue, 1, volume); 1 = kAudioQueueParam_Volume
  EndIf
EndProcedure

Procedure AudioStream_Start()
  If AudioStream_Queue
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf1)
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf2)
    AudioQueueStart(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Stop()
  If AudioStream_Queue
    AudioQueueStop(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Dispose()
  If AudioStream_Queue
    AudioQueueDispose(AudioStream_Queue)
    AudioStream_Queue = 0 
  EndIf
EndProcedure

_________________
macOS 10.15 Catalina, PB 5.71 x64


Last edited by wilbert on Tue Feb 26, 2013 11:12 am, edited 4 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Mon Feb 25, 2013 6:42 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
Example code (mono)
Code:
EnableExplicit

XIncludeFile "AudioStream.pbi"

Global Phase.d

Procedure SampleCallback(*out.AudioStreamSamples)
  Protected i = 0
  While i < #AUDIOBUFFER_SAMPLES
    *out\s[i] = Sin(Phase) / 6
    Phase + 0.06
    i + 1
  Wend
EndProcedure

AudioStream_Init(@SampleCallback())
AudioStream_SetVolume(0.7)
AudioStream_Start()

MessageRequester("Audio Synthesis Demo", "Playing audio")

AudioStream_Dispose()


Example code (stereo)
Code:
EnableExplicit

XIncludeFile "AudioStream.pbi"

Global Phase.d

Procedure SampleCallback(*out.AudioStreamSamples)
  Protected i = 0
  While i < #AUDIOBUFFER_SAMPLES
    *out\ss[i]\l = Sin(Phase) / 6
    *out\ss[i]\r = Sin(Phase * 2) / 6
    Phase + 0.06
    i + 1
  Wend
EndProcedure

AudioStream_Init(@SampleCallback(), #True)
AudioStream_SetVolume(0.7)
AudioStream_Start()

MessageRequester("Audio Synthesis Demo", "Playing audio")

AudioStream_Dispose()

_________________
macOS 10.15 Catalina, PB 5.71 x64


Last edited by wilbert on Tue Feb 26, 2013 11:13 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Mon Feb 25, 2013 8:39 pm 
Offline
Addict
Addict

Joined: Mon Aug 04, 2008 10:56 pm
Posts: 1108
Location: Seattle, USA
Thanks wilbert!

It works fine. Now just to figure out what to do with it... :)

_________________
MacBook Pro-r, OSX 10.14.6 , PB 5.70LTS


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 9:21 am 
Offline
Addict
Addict
User avatar

Joined: Sun Apr 27, 2003 8:12 am
Posts: 2017
Location: USA
Jiminy Cricket!!!

What ever you do, don't do "*output + 2" with headphones on.

Nice work wilbert! But I'll wait till day, when I don't need headphones on to fiddle around with it. ;)

_________________
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef

Mac: 10.13.6 / 1.4GHz Core 2 Duo / 2GB DDR3 / Nvidia 320M
PC: Win 7 / AMD 64 4000+ / 3GB DDR / Nvidia 720GT


Even the vine knows it surroundings but the man with eyes does not.


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 11:09 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
J. Baker wrote:
What ever you do, don't do "*output + 2" with headphones on.

I made a similar mistake with speakers on; wasn't nice :shock:

Anyway, I changed the include file and example above.
I changed it so mono is 1 x 64-bit float and stereo is 2 x 32-bit float.
This way the number of samples is the same for both and with a structure union it is easier to access the samples (no need to increase a memory pointer).

@William,
Something like this would be nice http://tonematrix.audiotool.com
It's created by someone else using Flash but I suppose it should be possible to create something similar using the canvas gadget.

_________________
macOS 10.15 Catalina, PB 5.71 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 7:02 pm 
Offline
Addict
Addict

Joined: Mon Aug 04, 2008 10:56 pm
Posts: 1108
Location: Seattle, USA
wilbert,

tonematrix is a lot of fun and the site is a real time-waster :) I agree it looks like a canvas gadget waiting to happen.

I was listening to http://www.audiotool.com/track/yesterday-pa8gus/ ...enviro-synthesis (just made that up)

_________________
MacBook Pro-r, OSX 10.14.6 , PB 5.70LTS


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 8:35 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Apr 27, 2003 8:12 am
Posts: 2017
Location: USA
wilbert wrote:
J. Baker wrote:
What ever you do, don't do "*output + 2" with headphones on.

I made a similar mistake with speakers on; wasn't nice :shock:

Anyway, I changed the include file and example above.
I changed it so mono is 1 x 64-bit float and stereo is 2 x 32-bit float.
This way the number of samples is the same for both and with a structure union it is easier to access the samples (no need to increase a memory pointer).

Cool. ;)

_________________
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef

Mac: 10.13.6 / 1.4GHz Core 2 Duo / 2GB DDR3 / Nvidia 320M
PC: Win 7 / AMD 64 4000+ / 3GB DDR / Nvidia 720GT


Even the vine knows it surroundings but the man with eyes does not.


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 9:29 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Apr 27, 2003 8:12 am
Posts: 2017
Location: USA
Hello? Who is it? :D

Code:
EnableExplicit

XIncludeFile "AudioStream.pbi"

Global Phase.d

Procedure SampleCallback(*out.AudioStreamSamples)
  Protected i = 0
  While i < #AUDIOBUFFER_SAMPLES
    *out\s[i] = Sin(Phase) / 3
     If i / 500
       Phase + 0.35
     Else
       Phase + 0.25
     EndIf
    i + 1
  Wend
EndProcedure

Define Ring = 0

AudioStream_Init(@SampleCallback())
AudioStream_SetVolume(0.7)

Repeat
 
 AudioStream_Start()

  Delay(1000)

   AudioStream_Stop()

  Delay(100)

 Ring + 1

Until Ring = 2

AudioStream_Dispose()

_________________
www.posemotion.com

PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef

Mac: 10.13.6 / 1.4GHz Core 2 Duo / 2GB DDR3 / Nvidia 320M
PC: Win 7 / AMD 64 4000+ / 3GB DDR / Nvidia 720GT


Even the vine knows it surroundings but the man with eyes does not.


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Feb 26, 2013 10:00 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
@Joe, was that your phone ringing ? :wink:

@William, you are right, it is fun that tone matrix. Don't know if it would be hard to recreate using PB.

_________________
macOS 10.15 Catalina, PB 5.71 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Thu Sep 15, 2016 12:03 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
For MacroTune we used the hardware abstraction layer which is more low-level.
Code:
ImportC ""
  AudioUnitSetVolume__(Unit, ID, Scope, Element, Value.f, BufferOffsetInFrames) As "_AudioUnitSetParameter"
EndImport

#kAudioDevicePropertyBufferFrameSize  = $6673697a; 'fsiz'
#kAudioFormatFlagIsPacked             = 8
#kAudioFormatFlagIsSignedInteger      = 4
#kAudioFormatLinearPCM                = $6C70636D; 'lpcm'
#kAudioUnitManufacturer_Apple         = $6170706C; 'appl'
#kAudioUnitProperty_SetRenderCallback = 23
#kAudioUnitProperty_StreamFormat      = 8
#kAudioUnitScope_Input                = 1
#kAudioUnitSubType_DefaultOutput      = $64656620; 'def '
#kAudioUnitType_Output                = $61756F75; 'auou'
#kHALOutputParam_Volume               = 14

Structure AudioComponentDescription
  componentType.l
  componentSubType.l
  componentManufacturer.l
  componentFlags.l
  componentFlagsMask.l
EndStructure

Structure AudioStreamBasicDescription
  mSampleRate.d
  mFormatID.l
  mFormatFlags.l
  mBytesPerPacket.l
  mFramesPerPacket.l
  mBytesPerFrame.l
  mChannelsPerFrame.l
  mBitsPerChannel.l
  mReserved.l
EndStructure

Structure AURenderCallbackStruct
  *inputProc
  inputProcRefCon.i
EndStructure


Global Audio_Unit.i

Procedure Audio_SetVolume(Volume); 0 - 100
  Protected factor.f
  If Volume
    factor = Pow(10, 40 * (Volume - 100) * 0.0005)
  EndIf
  AudioUnitSetVolume__(Audio_Unit, #kHALOutputParam_Volume, #kAudioUnitScope_Input, 0, factor, 0)
EndProcedure

Procedure Audio_Init(*CallbackFunction, BufferSize.l = 2048)
 
  Protected ACD.AudioComponentDescription
  Protected ASBD.AudioStreamBasicDescription
  Protected CallbackStruct.AURenderCallbackStruct
 
  ACD\componentType         = #kAudioUnitType_Output
  ACD\componentSubType      = #kAudioUnitSubType_DefaultOutput
  ACD\componentManufacturer = #kAudioUnitManufacturer_Apple
 
  ASBD\mSampleRate        = 44100
  ASBD\mFormatID          = #kAudioFormatLinearPCM
  ASBD\mFormatFlags       = #kAudioFormatFlagIsPacked | #kAudioFormatFlagIsSignedInteger
  ASBD\mBytesPerPacket    = 4
  ASBD\mFramesPerPacket   = 1
  ASBD\mBytesPerFrame     = 4
  ASBD\mChannelsPerFrame  = 2
  ASBD\mBitsPerChannel    = 16
 
  CallbackStruct\inputProc = *CallbackFunction

  AudioComponentInstanceNew_(AudioComponentFindNext_(#Null, @ACD), @Audio_Unit)
  AudioUnitSetProperty_(Audio_Unit, #kAudioUnitProperty_SetRenderCallback, #kAudioUnitScope_Input, 0, @CallbackStruct, SizeOf(AURenderCallbackStruct))
  AudioUnitSetProperty_(Audio_Unit, #kAudioUnitProperty_StreamFormat, #kAudioUnitScope_Input, 0, @ASBD, SizeOf(AudioStreamBasicDescription))
  AudioUnitSetProperty_(Audio_Unit, #kAudioDevicePropertyBufferFrameSize, #kAudioUnitScope_Input, 0, @BufferSize, SizeOf(Long))
  AudioUnitInitialize_(Audio_Unit)
 
EndProcedure

Procedure Audio_Start()
  ProcedureReturn Bool(AudioOutputUnitStart_(Audio_Unit) = 0)
EndProcedure

Procedure Audio_Stop()
  AudioOutputUnitStop_(Audio_Unit)
EndProcedure

Procedure Audio_Terminate()
  If Audio_Unit
    AudioOutputUnitStop_(Audio_Unit)
    AudioUnitUninitialize_(Audio_Unit)
    AudioComponentInstanceDispose_(Audio_Unit)
    Audio_Unit = 0
  EndIf
EndProcedure


; *** Audio test ***

Global Phase.f = 0
Global Phase_add.f = 0.1
Global Sample.w

ProcedureC Callback(*inRefcon, *ioActionFlags, *inTimeStamp, inBusNumber.l, inNumberFrames.l, *ioData)
  Protected i.i, *out.Word = PeekI(*ioData + SizeOf(Integer) + 8)
  While i < inNumberFrames
    Phase + Phase_add
    If Phase >= 2*#PI : Phase - 2*#PI : EndIf
    Sample = Sin(Phase) * 32767
    *out\w = Sample : *out + 2
    *out\w = Sample : *out + 2
    i + 1
  Wend
  ProcedureReturn 0
EndProcedure

Audio_Init(@Callback())
Audio_SetVolume(50)

If Audio_Start()
  MessageRequester("", "Click to close application")
  Audio_Terminate()
EndIf

_________________
macOS 10.15 Catalina, PB 5.71 x64


Last edited by wilbert on Fri Aug 09, 2019 3:23 pm, edited 8 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Thu Sep 15, 2016 1:37 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 473
Hi Wilbert,

thanks for these example.
I try to use it to play back a WAVE file but it crashes.
Do you have any idea why?

Code:
EnableExplicit
;-AudioStream.pbi

#AUDIOBUFFER_SIZE = 16384
#AUDIOBUFFER_SAMPLES = #AUDIOBUFFER_SIZE >> 3



    #kAudioFormatFlagIsFloat                     = (1 << 0)     ;// 0x1
    #kAudioFormatFlagIsBigEndian                 = (1 << 1)     ;// 0x2
    #kAudioFormatFlagIsSignedInteger             = (1 << 2)     ;// 0x4
    #kAudioFormatFlagIsPacked                    = (1 << 3)     ;// 0x8
    #kAudioFormatFlagIsAlignedHigh               = (1 << 4)     ;// 0x10
    #kAudioFormatFlagIsNonInterleaved            = (1 << 5)     ;// 0x20
    #kAudioFormatFlagIsNonMixable                = (1 << 6)     ;// 0x40
    #kAudioFormatFlagsAreAllClear                = (1 << 31)
   
    #kLinearPCMFormatFlagIsFloat                 = #kAudioFormatFlagIsFloat
    #kLinearPCMFormatFlagIsBigEndian             = #kAudioFormatFlagIsBigEndian
    #kLinearPCMFormatFlagIsSignedInteger         = #kAudioFormatFlagIsSignedInteger
    #kLinearPCMFormatFlagIsPacked                = #kAudioFormatFlagIsPacked
    #kLinearPCMFormatFlagIsAlignedHigh           = #kAudioFormatFlagIsAlignedHigh
    #kLinearPCMFormatFlagIsNonInterleaved        = #kAudioFormatFlagIsNonInterleaved
    #kLinearPCMFormatFlagIsNonMixable            = #kAudioFormatFlagIsNonMixable
    #kLinearPCMFormatFlagsSampleFractionShift    = 7
    #kLinearPCMFormatFlagsSampleFractionMask     = ($3F << #kLinearPCMFormatFlagsSampleFractionShift)
    #kLinearPCMFormatFlagsAreAllClear            = #kAudioFormatFlagsAreAllClear
   
    #kAppleLosslessFormatFlag_16BitSourceData    = 1
    #kAppleLosslessFormatFlag_20BitSourceData    = 2
    #kAppleLosslessFormatFlag_24BitSourceData    = 3
    #kAppleLosslessFormatFlag_32BitSourceData    = 4

   
Structure AudioStreamBasicDescription
  mSampleRate.d
  mFormatID.l
  mFormatFlags.l
  mBytesPerPacket.l
  mFramesPerPacket.l
  mBytesPerFrame.l
  mChannelsPerFrame.l
  mBitsPerChannel.l
  mReserved.l
EndStructure

Structure AudioQueueBuffer
  mAudioDataBytesCapacity.i
  mAudioData.i
  mAudioDataByteSize.i
  mUserData.i
  mPacketDescriptionCapacity.i
  mPacketDescriptions.i
  mPacketDescriptionCount.i
EndStructure

Structure AudioStreamStereoSample
  l.f
  r.f
EndStructure

Structure AudioStreamSamples
  StructureUnion
    s.d[0]
    ss.AudioStreamStereoSample[0]
  EndStructureUnion
EndStructure

ImportC "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
  AudioQueueAllocateBuffer(inAQ, inBufferByteSize, *outBuffer)
  AudioQueueDispose(inAQ, inImmediate = #True)
  AudioQueueEnqueueBuffer(inAQ, inBuffer, inNumPacketDescs = 0, *inPacketDescs = #Null)
  AudioQueueNewOutput(*inFormat, inCallbackProc, *inUserData, inCallbackRunLoop, inCallbackRunLoopMode, inFlags, *outAQ)
  AudioQueueSetParameter(inAQ, inParamID, inValue.f)
  AudioQueueStart(inAQ, *inStartTime = #Null)
  AudioQueueStop(inAQ, inImmediate = #True)
EndImport

Prototype AudioStream_Callback_Proto(*SampleData.Float)
Global AudioStream_Callback.AudioStream_Callback_Proto

Global *AudioStream_Buf1.AudioQueueBuffer, *AudioStream_Buf2.AudioQueueBuffer
Global AudioStream_Queue = 0

ProcedureC AudioStream_Callback_(*ptr, queue, *buf.AudioQueueBuffer)
  AudioStream_Callback(*buf\mAudioData)
  AudioQueueEnqueueBuffer(queue, *buf)
EndProcedure

Procedure AudioStream_Init(*Callback, Stereo = #False)
  AudioStream_Callback = *Callback
  Protected fmt.AudioStreamBasicDescription
  fmt\mSampleRate = 44100
  fmt\mFormatID = $6C70636D; kAudioFormatLinearPCM
  fmt\mFormatFlags = #kAudioFormatFlagIsBigEndian ; #kAudioFormatFlagIsFloat
  fmt\mFramesPerPacket = 1
  fmt\mBytesPerFrame = 8
  fmt\mBytesPerPacket = 8
  fmt\
  If Stereo
    fmt\mChannelsPerFrame = 2
    fmt\mBitsPerChannel = 16
  Else
    fmt\mChannelsPerFrame = 1
    fmt\mBitsPerChannel = 64
  EndIf
  If AudioQueueNewOutput(@fmt, @AudioStream_Callback_(), #Null, #Null, #Null, 0, @AudioStream_Queue) = 0
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf1)
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf2)
    *AudioStream_Buf1\mAudioDataByteSize = #AUDIOBUFFER_SIZE
    *AudioStream_Buf2\mAudioDataByteSize = #AUDIOBUFFER_SIZE
  EndIf
EndProcedure

Procedure AudioStream_SetVolume(volume.f)
  If AudioStream_Queue
    AudioQueueSetParameter(AudioStream_Queue, 1, volume); 1 = kAudioQueueParam_Volume
  EndIf
EndProcedure

Procedure AudioStream_Start()
  If AudioStream_Queue
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf1)
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf2)
    AudioQueueStart(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Stop()
  If AudioStream_Queue
    AudioQueueStop(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Dispose()
  If AudioStream_Queue
    AudioQueueDispose(AudioStream_Queue)
    AudioStream_Queue = 0 
  EndIf
EndProcedure

;-Main


; XIncludeFile "AudioStream.pbi"
Define FileName.s = "/Users/YourNmae/Desktop/16bit_44100WAVE_Stereo.wav"
If OpenFile(1, FileName)
  Define FileSize.i = Lof(1)
  Global Dim WaveBuffer.w(FileSize)
  Global WaveLength =30000
  ReadData(1, @WaveBuffer(), FileSize)
 
  CloseFile(1)
EndIf


Procedure SampleCallback(*out.AudioStreamSamples)
  Protected i = 0
  Protected L = 128 ;Start of the Wave Samples

  While L = < WaveLength
    While i < #AUDIOBUFFER_SAMPLES
      *out\ss[i]\l = WaveBuffer(L )
      *out\ss[i]\r = WaveBuffer(L  +1)
     
      L +1
      i + 1
    Wend
    i = 0
    L +1
  Wend

EndProcedure

AudioStream_Init(@SampleCallback(), #True)
AudioStream_SetVolume(0.5)
AudioStream_Start()

MessageRequester("Audio Synthesis Demo", "Playing audio")

AudioStream_Dispose()


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Thu Sep 15, 2016 3:19 pm 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
@Wolfram,
There were multiple things wrong with your code.
Here's my attempt.
Code:
EnableExplicit
;-AudioStream.pbi

#AUDIOBUFFER_SIZE = 8192
#AUDIOBUFFER_SAMPLES = #AUDIOBUFFER_SIZE >> 2



    #kAudioFormatFlagIsFloat                     = (1 << 0)     ;// 0x1
    #kAudioFormatFlagIsBigEndian                 = (1 << 1)     ;// 0x2
    #kAudioFormatFlagIsSignedInteger             = (1 << 2)     ;// 0x4
    #kAudioFormatFlagIsPacked                    = (1 << 3)     ;// 0x8
    #kAudioFormatFlagIsAlignedHigh               = (1 << 4)     ;// 0x10
    #kAudioFormatFlagIsNonInterleaved            = (1 << 5)     ;// 0x20
    #kAudioFormatFlagIsNonMixable                = (1 << 6)     ;// 0x40
    #kAudioFormatFlagsAreAllClear                = (1 << 31)
   
    #kLinearPCMFormatFlagIsFloat                 = #kAudioFormatFlagIsFloat
    #kLinearPCMFormatFlagIsBigEndian             = #kAudioFormatFlagIsBigEndian
    #kLinearPCMFormatFlagIsSignedInteger         = #kAudioFormatFlagIsSignedInteger
    #kLinearPCMFormatFlagIsPacked                = #kAudioFormatFlagIsPacked
    #kLinearPCMFormatFlagIsAlignedHigh           = #kAudioFormatFlagIsAlignedHigh
    #kLinearPCMFormatFlagIsNonInterleaved        = #kAudioFormatFlagIsNonInterleaved
    #kLinearPCMFormatFlagIsNonMixable            = #kAudioFormatFlagIsNonMixable
    #kLinearPCMFormatFlagsSampleFractionShift    = 7
    #kLinearPCMFormatFlagsSampleFractionMask     = ($3F << #kLinearPCMFormatFlagsSampleFractionShift)
    #kLinearPCMFormatFlagsAreAllClear            = #kAudioFormatFlagsAreAllClear
   
    #kAppleLosslessFormatFlag_16BitSourceData    = 1
    #kAppleLosslessFormatFlag_20BitSourceData    = 2
    #kAppleLosslessFormatFlag_24BitSourceData    = 3
    #kAppleLosslessFormatFlag_32BitSourceData    = 4

   
Structure AudioStreamBasicDescription
  mSampleRate.d
  mFormatID.l
  mFormatFlags.l
  mBytesPerPacket.l
  mFramesPerPacket.l
  mBytesPerFrame.l
  mChannelsPerFrame.l
  mBitsPerChannel.l
  mReserved.l
EndStructure

Structure AudioQueueBuffer
  mAudioDataBytesCapacity.i
  mAudioData.i
  mAudioDataByteSize.i
  mUserData.i
  mPacketDescriptionCapacity.i
  mPacketDescriptions.i
  mPacketDescriptionCount.i
EndStructure

Structure AudioStreamStereoSample
  l.w
  r.w
EndStructure

Structure AudioStreamSamples
  ss.AudioStreamStereoSample[0]
EndStructure

ImportC "/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox"
  AudioQueueAllocateBuffer(inAQ, inBufferByteSize, *outBuffer)
  AudioQueueDispose(inAQ, inImmediate = #True)
  AudioQueueEnqueueBuffer(inAQ, inBuffer, inNumPacketDescs = 0, *inPacketDescs = #Null)
  AudioQueueNewOutput(*inFormat, inCallbackProc, *inUserData, inCallbackRunLoop, inCallbackRunLoopMode, inFlags, *outAQ)
  AudioQueueSetParameter(inAQ, inParamID, inValue.f)
  AudioQueueStart(inAQ, *inStartTime = #Null)
  AudioQueueStop(inAQ, inImmediate = #True)
EndImport

Prototype AudioStream_Callback_Proto(*SampleData.Float)
Global AudioStream_Callback.AudioStream_Callback_Proto

Global *AudioStream_Buf1.AudioQueueBuffer, *AudioStream_Buf2.AudioQueueBuffer
Global AudioStream_Queue = 0

ProcedureC AudioStream_Callback_(*ptr, queue, *buf.AudioQueueBuffer)
  AudioStream_Callback(*buf\mAudioData)
  AudioQueueEnqueueBuffer(queue, *buf)
EndProcedure

Procedure AudioStream_Init(*Callback)
  AudioStream_Callback = *Callback
  Protected fmt.AudioStreamBasicDescription
  fmt\mSampleRate = 44100
  fmt\mFormatID = $6C70636D; kAudioFormatLinearPCM
  fmt\mFormatFlags = #kAudioFormatFlagIsPacked | #kLinearPCMFormatFlagIsSignedInteger
  fmt\mFramesPerPacket = 1
  fmt\mBytesPerFrame = 4
  fmt\mBytesPerPacket = 4
  fmt\mChannelsPerFrame = 2
  fmt\mBitsPerChannel = 16
  If AudioQueueNewOutput(@fmt, @AudioStream_Callback_(), #Null, #Null, #Null, 0, @AudioStream_Queue) = 0
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf1)
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf2)
    *AudioStream_Buf1\mAudioDataByteSize = #AUDIOBUFFER_SIZE
    *AudioStream_Buf2\mAudioDataByteSize = #AUDIOBUFFER_SIZE
  EndIf
EndProcedure

Procedure AudioStream_SetVolume(volume.f)
  If AudioStream_Queue
    AudioQueueSetParameter(AudioStream_Queue, 1, volume); 1 = kAudioQueueParam_Volume
  EndIf
EndProcedure

Procedure AudioStream_Start()
  If AudioStream_Queue
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf1)
    AudioStream_Callback_(#Null, AudioStream_Queue, *AudioStream_Buf2)
    AudioQueueStart(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Stop()
  If AudioStream_Queue
    AudioQueueStop(AudioStream_Queue)
  EndIf
EndProcedure

Procedure AudioStream_Dispose()
  If AudioStream_Queue
    AudioQueueDispose(AudioStream_Queue)
    AudioStream_Queue = 0 
  EndIf
EndProcedure

;-Main


; XIncludeFile "AudioStream.pbi"
Define FileName.s = "/Users/YourNmae/Desktop/16bit_44100WAVE_Stereo.wav"
If OpenFile(1, FileName)
  Define FileSize.i = Lof(1)
  Global SamplePos = 44
  Global NumSamples = FileSize / SizeOf(AudioStreamStereoSample)
  Global Dim WaveBuffer.AudioStreamStereoSample(NumSamples)
  ReadData(1, @WaveBuffer(), FileSize)
 
  CloseFile(1)
EndIf


Procedure SampleCallback(*out.AudioStreamSamples)
  Protected i = 0
  While i < #AUDIOBUFFER_SAMPLES
    If SamplePos < NumSamples
      *out\ss[i]\l = WaveBuffer(SamplePos)\l
      *out\ss[i]\r = WaveBuffer(SamplePos)\r
      SamplePos + 1     
    Else
      *out\ss[i]\l = 0
      *out\ss[i]\r = 0
    EndIf
    i + 1
  Wend

EndProcedure

AudioStream_Init(@SampleCallback())
AudioStream_SetVolume(0.5)
AudioStream_Start()

MessageRequester("Audio Synthesis Demo", "Playing audio")

AudioStream_Dispose()


AUHAL version
Code:
ImportC ""
  AudioUnitSetVolume__(Unit, ID, Scope, Element, Value.f, BufferOffsetInFrames) As "_AudioUnitSetParameter"
EndImport

DataSection
  dOut:
  Data.l $61756f75,$64656620,$6170706c,0,0
  PCM16Bit:
  Data.l 0,$40E58880,$6C70636D,12,4,1,4,2,16,0
  PCM32BitFloat:
  Data.l 0,$40E58880,$6C70636D,1,8,1,8,2,32,0
EndDataSection

Global Audio_Unit.i

Procedure Audio_SetVolume(Volume); 0 - 100
  Protected factor.f
  If Volume
    factor = Pow(10, 40 * (Volume - 100) * 0.0005)
  EndIf
  AudioUnitSetVolume__(Audio_Unit, 14, 1, 0, factor, 0)
EndProcedure

Procedure Audio_Init(*CallbackFunction, BufferSize.l = 2048)
  Protected Dim CallbackStruct.i(1) : CallbackStruct(0) = *CallbackFunction
  AudioComponentInstanceNew_(AudioComponentFindNext_(#Null, ?dOut), @Audio_Unit)
  AudioUnitSetProperty_(Audio_Unit, 23, 1, 0, @CallbackStruct(), SizeOf(Integer) << 1)
  AudioUnitSetProperty_(Audio_Unit, 8, 1, 0, ?PCM16Bit, 40)
  AudioUnitSetProperty_(Audio_Unit, $6673697a, 1, 0, @BufferSize, 4)
  AudioUnitInitialize_(Audio_Unit)
EndProcedure

Procedure Audio_Start()
  ProcedureReturn Bool(AudioOutputUnitStart_(Audio_Unit) = 0)
EndProcedure

Procedure Audio_Stop()
  AudioOutputUnitStop_(Audio_Unit)
EndProcedure

Procedure Audio_Terminate()
  If Audio_Unit
    AudioOutputUnitStop_(Audio_Unit)
    AudioUnitUninitialize_(Audio_Unit)
    AudioComponentInstanceDispose_(Audio_Unit)
    Audio_Unit = 0
  EndIf
EndProcedure


;-Main

Structure AudioStreamStereoSample
  l.w
  r.w
EndStructure

Structure AudioStreamSamples
  ss.AudioStreamStereoSample[0]
EndStructure

Define FileName.s = "/Users/YourNmae/Desktop/16bit_44100WAVE_Stereo.wav"
If OpenFile(1, FileName)
  Define FileSize.i = Lof(1)
  Global SamplePos = 44
  Global NumSamples = FileSize / SizeOf(AudioStreamStereoSample)
  Global Dim WaveBuffer.AudioStreamStereoSample(NumSamples)
  ReadData(1, @WaveBuffer(), FileSize)
 
  CloseFile(1)
EndIf


ProcedureC SampleCallback(*inRefcon, *ioActionFlags, *inTimeStamp, inBusNumber.l, inNumberFrames.l, *ioData)
  Protected i.i, *out.AudioStreamSamples = PeekI(*ioData + SizeOf(Integer) + 8)
  While i < inNumberFrames
    If SamplePos < NumSamples
      *out\ss[i]\l = WaveBuffer(SamplePos)\l
      *out\ss[i]\r = WaveBuffer(SamplePos)\r
      SamplePos + 1     
    Else
      *out\ss[i]\l = 0
      *out\ss[i]\r = 0
    EndIf
    i + 1
  Wend

EndProcedure

Audio_Init(@SampleCallback())
Audio_SetVolume(50)
Audio_Start()

MessageRequester("Audio Synthesis Demo", "Playing audio")

Audio_Terminate()

_________________
macOS 10.15 Catalina, PB 5.71 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Sat Sep 16, 2017 11:39 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 473
Hello,

I'm trying to play a 16 bit mono WAVE file by using this code, but there is something wrong.
The WAVE file plays to slow. This is not happened if I use 4 for BytesPerFrame and mBytesPerPacket and 2 per ChannelsPerFrame


Code:
Protected fmt.AudioStreamBasicDescription
  fmt\mSampleRate = SampleRate
  fmt\mFormatID = $6C70636D; kAudioFormatLinearPCM
  fmt\mFormatFlags = #kAudioFormatFlagIsPacked | #kLinearPCMFormatFlagIsSignedInteger
  fmt\mFramesPerPacket = 1
  fmt\mBytesPerFrame = 2
  fmt\mBytesPerPacket = 2
  fmt\mChannelsPerFrame = 1
  fmt\mBitsPerChannel = 16
  If AudioQueueNewOutput(@fmt, @AudioStream_Callback_(), #Null, #Null, #Null, 0, @AudioStream_Queue) = 0
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf1)
    AudioQueueAllocateBuffer(AudioStream_Queue, #AUDIOBUFFER_SIZE, @*AudioStream_Buf2)
    *AudioStream_Buf1\mAudioDataByteSize = #AUDIOBUFFER_SIZE
    *AudioStream_Buf2\mAudioDataByteSize = #AUDIOBUFFER_SIZE
  EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Sep 19, 2017 6:24 am 
Offline
PureBasic Expert
PureBasic Expert

Joined: Sun Aug 08, 2004 5:21 am
Posts: 3548
Location: Netherlands
Wolfram wrote:
I'm trying to play a 16 bit mono WAVE file by using this code, but there is something wrong.
The WAVE file plays to slow. This is not happened if I use 4 for BytesPerFrame and mBytesPerPacket and 2 per ChannelsPerFrame

I'm not sure why this is happening. You can try adding #kAudioFormatFlagIsNonInterleaved to the format flags (value of the constant is 32).
If it doesn't work, maybe the AUHAL version (see above) works.

_________________
macOS 10.15 Catalina, PB 5.71 x64


Top
 Profile  
Reply with quote  
 Post subject: Re: Audio Synthesis
PostPosted: Tue Sep 19, 2017 4:42 pm 
Offline
Enthusiast
Enthusiast

Joined: Thu May 30, 2013 4:39 pm
Posts: 473
Hi Wilbert,

I already tried that.
Do you get the same effect on your system?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye