1/*
2 * Copyright 2003-2010 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Marcus Overhagen
7 */
8#ifndef _MIXER_CORE_H
9#define _MIXER_CORE_H
10
11
12#include "MixerSettings.h"
13
14#include <Buffer.h>
15#include <Locker.h>
16#include <TimeSource.h>
17
18
19class AudioMixer;
20class BBufferGroup;
21class MixerInput;
22class MixerOutput;
23class Resampler;
24
25
26// The number of "enum media_multi_channels" types from MediaDefs.h
27// XXX should be 18, but limited to 12 here
28#define MAX_CHANNEL_TYPES	12
29// XXX using a dedicated mono channel, this should be channel type 31
30//     but for now we redefine type 12
31#define B_CHANNEL_MONO		B_CHANNEL_TOP_CENTER
32
33#define MIXER_PROCESS_EVENT BTimedEventQueue::B_USER_EVENT+10
34#define MIXER_SCHEDULE_EVENT BTimedEventQueue::B_USER_EVENT+11
35
36
37class MixerCore {
38public:
39								MixerCore(AudioMixer* node);
40	virtual						~MixerCore();
41
42			MixerSettings*		Settings();
43			void				UpdateResamplingAlgorithm();
44
45	// To avoid calling Settings()->AttenuateOutput() for every outgoing
46	// buffer, this setting is cached in fOutputGain and must be set by
47	// the audio mixer node using SetOutputAttenuation()
48			void				SetOutputAttenuation(float gain);
49			MixerInput*			AddInput(const media_input& input);
50			MixerOutput*		AddOutput(const media_output& output);
51
52			bool				RemoveInput(int32 inputID);
53			bool				RemoveOutput();
54			int32				CreateInputID();
55
56	// index = 0 to count-1, NOT inputID
57			MixerInput*			Input(int index);
58			MixerOutput*		Output();
59
60			bool				Lock();
61			bool				LockWithTimeout(bigtime_t timeout);
62			bool				IsLocked() const;
63			void				Unlock();
64
65			void				Process();
66			bigtime_t			PickEvent();
67
68			void				BufferReceived(BBuffer* buffer,
69									bigtime_t lateness);
70
71			void				InputFormatChanged(int32 inputID,
72									const media_multi_audio_format& format);
73			void				OutputFormatChanged(
74									const media_multi_audio_format& format);
75
76			void				SetOutputBufferGroup(BBufferGroup* group);
77			void				SetTimingInfo(BTimeSource* timeSource,
78									bigtime_t downstreamLatency);
79			void				EnableOutput(bool enabled);
80			bool				Start();
81			bool				Stop();
82
83			void				StartMixThread();
84			void				StopMixThread();
85			uint32				OutputChannelCount();
86
87private:
88			void				_UpdateResamplers(
89									const media_multi_audio_format& format);
90			void				_ApplyOutputFormat();
91	static	int32				_MixThreadEntry(void* arg);
92			void				_MixThread();
93
94private:
95			BLocker*			fLocker;
96			BList*				fInputs;
97			MixerOutput*		fOutput;
98			int32				fNextInputID;
99			bool				fRunning;
100									// true = the mix thread is running
101
102			bool				fStarted;
103									// true = mix thread should be
104									// started of it is not running
105
106			bool				fOutputEnabled;
107									// true = mix thread should be
108									// started of it is not running
109
110			Resampler**			fResampler; // array
111			float*				fMixBuffer;
112			int32				fMixBufferFrameRate;
113			int32				fMixBufferFrameCount;
114			int32				fMixBufferChannelCount;
115			int32*				fMixBufferChannelTypes; //array
116			bool				fDoubleRateMixing;
117			bigtime_t			fDownstreamLatency;
118			MixerSettings*		fSettings;
119			AudioMixer*			fNode;
120			BBufferGroup*		fBufferGroup;
121			BTimeSource*		fTimeSource;
122			thread_id			fMixThread;
123			sem_id				fMixThreadWaitSem;
124			bool				fHasEvent;
125			bigtime_t			fEventTime;
126			bigtime_t			fEventLatency;
127			float				fOutputGain;
128
129	friend class MixerInput;
130		// NOTE: debug only
131};
132
133
134inline bool
135MixerCore::Lock()
136{
137	return fLocker->Lock();
138}
139
140
141inline bool
142MixerCore::LockWithTimeout(bigtime_t timeout)
143{
144	return fLocker->LockWithTimeout(timeout) == B_OK;
145}
146
147
148inline bool
149MixerCore::IsLocked() const
150{
151	return fLocker->IsLocked();
152}
153
154
155inline void
156MixerCore::Unlock()
157{
158	fLocker->Unlock();
159}
160
161
162inline void
163MixerCore::Process()
164{
165	release_sem(fMixThreadWaitSem);
166}
167
168
169inline bigtime_t
170MixerCore::PickEvent()
171{
172	return fTimeSource->RealTimeFor(fEventTime, 0)
173		- fEventLatency - fDownstreamLatency;
174}
175
176
177#endif // _MIXER_CORE_H
178