PureBasic Forum
https://www.purebasic.fr/english/

Audio Synthesis
https://www.purebasic.fr/english/viewtopic.php?f=19&t=53672
Page 1 of 3

Author:  wilbert [ Mon Feb 25, 2013 6:40 pm ]
Post subject:  Audio Synthesis

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

Author:  wilbert [ Mon Feb 25, 2013 6:42 pm ]
Post subject:  Re: Audio Synthesis

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()

Author:  WilliamL [ Mon Feb 25, 2013 8:39 pm ]
Post subject:  Re: Audio Synthesis

Thanks wilbert!

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

Author:  J. Baker [ Tue Feb 26, 2013 9:21 am ]
Post subject:  Re: Audio Synthesis

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. ;)

Author:  wilbert [ Tue Feb 26, 2013 11:09 am ]
Post subject:  Re: Audio Synthesis

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.

Author:  WilliamL [ Tue Feb 26, 2013 7:02 pm ]
Post subject:  Re: Audio Synthesis

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)

Author:  J. Baker [ Tue Feb 26, 2013 8:35 pm ]
Post subject:  Re: Audio Synthesis

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. ;)

Author:  J. Baker [ Tue Feb 26, 2013 9:29 pm ]
Post subject:  Re: Audio Synthesis

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()

Author:  wilbert [ Tue Feb 26, 2013 10:00 pm ]
Post subject:  Re: Audio Synthesis

@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.

Author:  wilbert [ Thu Sep 15, 2016 12:03 pm ]
Post subject:  Re: Audio Synthesis

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

Author:  Wolfram [ Thu Sep 15, 2016 1:37 pm ]
Post subject:  Re: Audio Synthesis

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()

Author:  wilbert [ Thu Sep 15, 2016 3:19 pm ]
Post subject:  Re: Audio Synthesis

@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()

Author:  Wolfram [ Sat Sep 16, 2017 11:39 pm ]
Post subject:  Re: Audio Synthesis

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

Author:  wilbert [ Tue Sep 19, 2017 6:24 am ]
Post subject:  Re: Audio Synthesis

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.

Author:  Wolfram [ Tue Sep 19, 2017 4:42 pm ]
Post subject:  Re: Audio Synthesis

Hi Wilbert,

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

Page 1 of 3 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/