1 /* 2 * Copyright 2003-2009 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 19 class AudioMixer; 20 class BBufferGroup; 21 class MixerInput; 22 class MixerOutput; 23 class 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 class MixerCore { 34 public: 35 MixerCore(AudioMixer *node); 36 virtual ~MixerCore(); 37 38 MixerSettings* Settings(); 39 40 // To avoid calling Settings()->AttenuateOutput() for every outgoing 41 // buffer, this setting is cached in fOutputGain and must be set by 42 // the audio mixer node using SetOutputAttenuation() 43 void SetOutputAttenuation(float gain); 44 MixerInput* AddInput(const media_input& input); 45 MixerOutput* AddOutput(const media_output& output); 46 47 bool RemoveInput(int32 inputID); 48 bool RemoveOutput(); 49 int32 CreateInputID(); 50 51 // index = 0 to count-1, NOT inputID 52 MixerInput* Input(int index); 53 MixerOutput* Output(); 54 55 void Lock(); 56 bool LockWithTimeout(bigtime_t timeout); 57 bool LockFromMixThread(); 58 void Unlock(); 59 60 void BufferReceived(BBuffer* buffer, 61 bigtime_t lateness); 62 63 void InputFormatChanged(int32 inputID, 64 const media_multi_audio_format& format); 65 void OutputFormatChanged( 66 const media_multi_audio_format& format); 67 68 void SetOutputBufferGroup(BBufferGroup* group); 69 void SetTimingInfo(BTimeSource* timeSource, 70 bigtime_t downstream_latency); 71 void EnableOutput(bool enabled); 72 bool Start(); 73 bool Stop(); 74 75 void StartMixThread(); 76 void StopMixThread(); 77 uint32 OutputChannelCount(); 78 79 private: 80 void ApplyOutputFormat(); 81 static int32 _mix_thread_(void* arg); 82 void MixThread(); 83 84 private: 85 BLocker* fLocker; 86 BList* fInputs; 87 MixerOutput* fOutput; 88 int32 fNextInputID; 89 bool fRunning; 90 // true = the mix thread is running 91 92 bool fStarted; 93 // true = mix thread should be 94 // started of it is not running 95 96 bool fOutputEnabled; 97 // true = mix thread should be 98 // started of it is not running 99 100 Resampler** fResampler; // array 101 float* fMixBuffer; 102 int32 fMixBufferFrameRate; 103 int32 fMixBufferFrameCount; 104 int32 fMixBufferChannelCount; 105 int32* fMixBufferChannelTypes; //array 106 bool fDoubleRateMixing; 107 bigtime_t fDownstreamLatency; 108 MixerSettings* fSettings; 109 AudioMixer* fNode; 110 BBufferGroup* fBufferGroup; 111 BTimeSource* fTimeSource; 112 thread_id fMixThread; 113 sem_id fMixThreadWaitSem; 114 float fOutputGain; 115 116 friend class MixerInput; 117 // NOTE: debug only 118 }; 119 120 121 inline void 122 MixerCore::Lock() 123 { 124 fLocker->Lock(); 125 } 126 127 128 inline bool 129 MixerCore::LockWithTimeout(bigtime_t timeout) 130 { 131 return fLocker->LockWithTimeout(timeout) == B_OK; 132 } 133 134 135 inline void 136 MixerCore::Unlock() 137 { 138 fLocker->Unlock(); 139 } 140 141 142 inline bool 143 MixerCore::LockFromMixThread() 144 { 145 for (;;) { 146 if (LockWithTimeout(10000)) 147 return true; 148 // XXX accessing fMixThreadWaitSem is still a race condition :( 149 if (acquire_sem_etc(fMixThreadWaitSem, 1, B_RELATIVE_TIMEOUT, 0) 150 != B_WOULD_BLOCK) { 151 return false; 152 } 153 } 154 } 155 156 157 #endif // _MIXER_CORE_H 158