HomeForumSourceResearchGuide
Sign in to contribute to source. how it works
Component io.audio.AudioOut by barry
expand copy to clipboardexpand
data TrackStatus {
	int track
}

interface AudioOutputLib {
	event trackFinished(TrackStatus t)

	int output_new(int channels, int sampleRate)
	bool output_play(int handle, int trackHandle) //extra param to tell us when to emit a progress event after N frames through samples? extra param to loop?
	void output_stop(int handle, int trackHandle) //stop-and-discard
	void output_stop_all(int handle)
	void output_destroy(int handle)

	int track_new(int4 samples[], bool loop)
	bool track_append(int handle, int4 samples[], bool loop)
	void track_set_volume(int handle, int1 volume)
	void track_finish(int handle)
	int track_get_cursor(int handle)
	void track_destroy(int handle)
}

data TrackItem {
	AudioTrack track
	TrackItem next
}

component provides AudioOut(Destructor), AudioTrack(Destructor) requires native AudioOutputLib lib, io.Output out, data.IntUtil iu {
	
	implementation AudioOut {
		int handle

		TrackItem tracks
		TrackItem last

		eventsink trackEvents(EventData ed)
			{
			TrackStatus t = ed.details

			if (ed.type == AudioOutputLib.[trackFinished])
				{
				TrackItem tp = null
				TrackItem tw = tracks
				while (tw != null)
					{
					if (tw.track.handle == t.track)
						{
						if (tp == null)
							{
							tracks = tw.next
							if (tracks == null)
								last = null
							}
							else
							{
							tp.next = tw.next
							if (tp.next == null)
								last = tp
							}
						
						emitevent trackFinished(new TrackEvent(tw.track))
						break
						}
					
					tp = tw
					tw = tw.next
					}
				}
			}

		AudioOut:AudioOut(store AudioFormat format)
			{
			handle = lib.output_new(format.channels, format.sampleRate)
			sinkevent trackEvents(lib)
			}
		
		bool AudioOut:play(store AudioTrack track)
			{
			TrackItem newItem = new TrackItem(track)
			if (last == null)
				{
				tracks = newItem
				}
				else
				{
				last.next = newItem
				}
			last = newItem

			return lib.output_play(handle, track.handle)
			}
		
		void AudioOut:stop(AudioTrack track) //stop-and-discard
			{
			lib.output_stop(handle, track.handle)
			}
		
		void AudioOut:stopAll()
			{
			lib.output_stop_all(handle)
			}
		
		void Destructor:destroy()
			{
			lib.output_destroy(handle)
			}
	}

	implementation AudioTrack {
		
		int handle

		AudioTrack:AudioTrack(int4 samples[], opt bool loop)
			{
			handle = lib.track_new(samples, loop)
			}
		
		void AudioTrack:setVolume(int1 volume) //0-100
			{
			if (volume > 100) volume = 100
			lib.track_set_volume(handle, volume)
			}
		
		bool AudioTrack:append(int4 samples[], opt bool loop)
			{
			return lib.track_append(handle, samples, loop)
			}
		
		void AudioTrack:finish()
			{
			lib.track_finish(handle)
			}
		
		int AudioTrack:getFrameIndex()
			{
			return lib.track_get_cursor(handle)
			}
		
		void Destructor:destroy()
			{
			lib.track_destroy(handle)
			}
		}
}
Revision history
To propose a new revision to this entity, use dana source put -uc your/new/version.dn -n io.audio.AudioOut -m "reason for update" -u yourUsername
Version 4 by barry
Version 3 by barry
Version 2 by barry
Version 1 (this version) by barry
Notes for this version: Adds core audio output API