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