new mojo/audio/audio.monkey2

Home Forums Monkey 2 Code Library new mojo/audio/audio.monkey2

This topic contains 0 replies, has 1 voice, and was last updated by  AdamStrange 2 months, 3 weeks ago.

Viewing 1 post (of 1 total)
  • Author
    Posts
  • #10131

    AdamStrange
    Participant

    Here’s a modified version of the base sound and channel class.

    In essence i’ve added 256float to each sound that contains the waveform, these can be accessed through the new draw command.

    I’ve also added to the sound.new allowing you to create many synth type voices from the base 4 styles.

    | Channel will be automatically discarded when it finishes playing, or when it is stopped using [[Channel.Stop]]. #end Enum ChannelFlags AutoDiscard = 1 End Class Channel Extends Resource #rem monkeydoc Creates a new audio channel. If flags is ChannelFlags.AutoDiscard, then the channel will be automatically discarded when it finishes playing, or when it is stopped using [[Stop]]. #end Method New( flags:ChannelFlags = Null ) _flags = flags FlushAutoDiscard() alGenSources( 1, Varptr _alSource ) If _flags & ChannelFlags.AutoDiscard then _autoDiscard.Push( Self ) End Property Flags:ChannelFlags() Return _flags End #- 'jl added #rem monkeydoc True if channel is playing a stereo audio file. #end Property Stereo:bool() Return _stereo Setter( stereo:bool ) _stereo = stereo End #- #rem monkeydoc True if channel is playing audio. If the channel is playing audio but is in the paused state, this property will still return true. #end Property Playing:Bool() If Not _alSource Return False Local state := ALState() Return state = AL_PLAYING Or state = AL_PAUSED End #rem monkeydoc True if channel is paused. #end Property Paused:Bool() If Not _alSource Return False Return ALState() = AL_PAUSED Setter( paused:Bool ) If Not Playing Return If paused alSourcePause( _alSource ) Else alSourcePlay( _alSource ) Endif End #rem monkeydoc Channel volume in the range 0 to 1. #end Property Volume:Float() If Not _alSource Return 0 Return _volume Setter( volume:Float ) If Not _alSource Return _volume = Clamp( volume, 0.0, 1.0 ) alSourcef( _alSource, AL_GAIN, _volume ) End #rem monkeydoc Channel playback rate. #end Property Rate:Float() If Not _alSource Return 0 Return _rate Setter( rate:Float ) If Not _alSource Return _rate = rate alSourcef( _alSource, AL_PITCH, _rate ) End #rem monkeydoc Channel pan in the range -1 (left) to 1 (right). #end Property Pan:Float() If Not _alSource Return 0 Return _pan Setter( pan:Float) If Not _alSource Return _pan = Clamp( pan, -1.0, 1.0 )*1.5 If Not _stereo Then Local x := Sin( _pan ) Local z := -Cos( _pan ) alSource3f( _alSource, AL_POSITION, x, 0, z ) else ' Print "stereo "+_pan ' Local angles:ALfloat[] = New ALfloat[2] ' angles[0] = Pi/6.0 - _pan ' angles[1] = -Pi/6.0 - _pan ' ALfloat angles[2] = { (ALfloat)(M_PI/6.0 - angle), (ALfloat)(-M_PI/6.0 - angle) } ' alSourcefv( _alSource, AL_STEREO_ANGLES, Varptr angles[0] ) End If End #- 'JL added #rem monkeydoc Channel playhead in samples. If the channel is playing audio this will return the position of the playhead in the played sound. #end Property Playhead:Double() If Not _alSource Return 0 ' Local proc:ALint ' alGetSourcei( _alSource,AL_BUFFERS_PROCESSED,Varptr proc ) ' Print "processed: "+proc Local playhead:ALfloat alGetSourcef( _alSource, AL_SAMPLE_OFFSET, Varptr playhead ) Return (float(playhead) / _length) ' local pos:float ' return alGetSourcef( _alSource, AL_SAMPLE_OFFSET, Varptr pos ) Setter( playhead:Float ) If Not _alSource Return local _playhead:ALfloat = Clamp( playhead, 0.0, 1.0 ) alSourcef( _alSource, AL_SAMPLE_OFFSET, _playhead ) End #- #rem monkeydoc Channel playhead sample offset. Gets or sets the sample offset of the sound currently playing. If the channel is playing when set, playback is immediately affected. If the channel is not playing when set, the offset will be applied when the Play method is invoked. #end Property PlayheadSample:Int() If Not _alSource Return 0 Local sample:Int alGetSourcei( _alSource, AL_SAMPLE_OFFSET, Varptr sample ) Return sample Setter( sample:Int ) If Not _alSource Return alSourcei( _alSource, AL_SAMPLE_OFFSET, sample ) End #rem monkeydoc Channel playhead time offset. Gets or sets the time offset of the sound currently playing. If the channel is playing when set, playback is immediately affected. If the channel is not playing when set, the offset will be applied when the Play method is invoked. #end Property PlayheadTime:Float() If Not _alSource Return 0 Local time:Float alGetSourcef( _alSource, AL_SEC_OFFSET, Varptr time ) Return time Setter( time:Float ) If Not _alSource Return alSourcef( _alSource, AL_SEC_OFFSET, time ) End #rem monkeydoc Plays a sound through the channel. #end Method Play( sound:Sound, loop:Bool = False ) If Not _alSource Or Not sound Or Not sound._alBuffer Return alSourcei( _alSource, AL_LOOPING,loop ? AL_TRUE Else AL_FALSE ) alSourcei( _alSource, AL_BUFFER, sound._alBuffer ) #- 'jl added _stereo = sound.Stereo _length = sound.Length #- alSourcePlay( _alSource ) End #if __TARGET__<>"emscripten" #rem monkeydoc @hidden - Highly experimental!!!!! #end Method WaitQueued( queued:Int ) While _queued>queued FlushProcessed() If _queued <= queued Return _waiting = True _future.Get() Wend End #rem monkeydoc @hidden - Highly experimental!!!!! #end Method Queue( data:AudioData ) Local buf:ALuint If Not _tmpBuffers _tmpBuffers = New Stack<ALuint> _freeBuffers = New Stack<ALuint> _future = New Future<Int> _waiting = False _queued = 0 _timer = New Timer( 60, Lambda() FlushProcessed() End ) Endif If _freeBuffers.Empty alGenBuffers( 1, Varptr buf ) _tmpBuffers.Push( buf ) Else buf = _freeBuffers.Pop() Endif alBufferData( buf, ALFormat( data.Format ), data.Data, data.Size, data.Hertz ) alSourceQueueBuffers( _alSource, 1, Varptr buf ) _queued += 1 Local state := ALState() If state = AL_INITIAL Or state = AL_STOPPED then alSourcePlay( _alSource ) End #endif #rem monkeydoc Stops channel. #end Method Stop() If Not _alSource Return alSourceStop( _alSource ) If _flags & ChannelFlags.AutoDiscard then Discard() End Protected #rem monkeydoc @hidden #end Method OnDiscard() Override If _alSource alDeleteSources( 1,Varptr _alSource ) _alSource=0 End #rem monkeydoc @hidden #end Method OnFinalize() Override If _alSource alDeleteSources( 1,Varptr _alSource ) End Private Field _flags:ChannelFlags Field _alSource:ALuint Field _volume:Float = 1 Field _rate:Float = 1 Field _pan:Float = 0 #- 'jladded field _stereo:bool = false field _length:int = 0 #- Global _autoDiscard := New Stack<Channel> Method ALState:ALenum() Local state:ALenum alGetSourcei( _alSource, AL_SOURCE_STATE, Varptr state ) Return state End Function FlushAutoDiscard() Local put := 0 For Local chan := Eachin _autoDiscard If Not chan._alSource then Continue If chan.ALState() <> AL_STOPPED then _autoDiscard[ put ] = chan put += 1 Continue Endif chan.Discard() Next _autoDiscard.Resize( put ) End #if __TARGET__<>"emscripten" Field _tmpBuffers:Stack<ALuint> Field _freeBuffers:Stack<ALuint> Field _future:Future<Int> Field _waiting:Bool Field _queued:Int Field _timer:Timer Method FlushProcessed:Int() Local proc:ALint alGetSourcei( _alSource, AL_BUFFERS_PROCESSED, Varptr proc ) If Not proc Return 0 For Local i := 0 Until proc Local buf:ALuint alSourceUnqueueBuffers( _alSource, 1, Varptr buf ) _queued -= 1 If _tmpBuffers.Contains( buf ) _freeBuffers.Push( buf ) Next If _waiting _waiting = False _future.Set( proc ) Endif Return proc End #endif End [/crayon]

    Here’s a quick shot of the draw command in operation with 3 different sound shown at different sizes. the bg color is drawn separately – hence the color change.

    You can see that both mono and stereo, 8 and 16 bit are correctly displayed along with the base filename (also a new addition)

    I’m sure someone might find it useful :0

Viewing 1 post (of 1 total)

You must be logged in to reply to this topic.