Cocoa Port: Refactor the hardware mic stuff out of CocoaDSController and into ClientInputHandler.
This commit is contained in:
parent
f8bbbec0ae
commit
f521ab1164
|
@ -73,7 +73,14 @@ ClientInputHandler::ClientInputHandler()
|
|||
_internalNoiseGenerator = new InternalNoiseGenerator;
|
||||
_whiteNoiseGenerator = new WhiteNoiseGenerator;
|
||||
_sineWaveGenerator = new SineWaveGenerator(250.0, MIC_SAMPLE_RATE);
|
||||
_selectedAudioFileGenerator = NULL;
|
||||
_selectedAudioFileGenerator = NULL; // Note that this value can be NULL.
|
||||
_hardwareMicSampleGenerator = _nullSampleGenerator;
|
||||
|
||||
_avgMicLevel = 0.0f;
|
||||
_avgMicLevelTotal = 0.0f;
|
||||
_avgMicLevelsRead = 0.0f;
|
||||
_isHardwareMicMuted = true;
|
||||
_isHardwareMicPaused = true;
|
||||
|
||||
_enableAutohold = false;
|
||||
|
||||
|
@ -83,7 +90,9 @@ ClientInputHandler::ClientInputHandler()
|
|||
_paddleValuePending = _paddleValueProcessing = _paddleValueApplied = 0;
|
||||
_paddleAdjustPending = _paddleAdjustProcessing = _paddleAdjustApplied = 0;
|
||||
|
||||
_softwareMicSampleGeneratorPending = _softwareMicSampleGeneratorProcessing = _softwareMicSampleGeneratorApplied = _nullSampleGenerator;
|
||||
_softwareMicSampleGeneratorPending = _nullSampleGenerator;
|
||||
_softwareMicSampleGeneratorProcessing = _nullSampleGenerator;
|
||||
_softwareMicSampleGeneratorApplied = _nullSampleGenerator;
|
||||
|
||||
memset(_clientInputPending, 0, sizeof(_clientInputPending));
|
||||
memset(_clientInputProcessing, 0, sizeof(_clientInputProcessing));
|
||||
|
@ -257,6 +266,35 @@ void ClientInputHandler::SetSineWaveFrequency(double freq)
|
|||
this->_sineWaveGenerator->setFrequency(freq);
|
||||
}
|
||||
|
||||
float ClientInputHandler::GetAverageMicLevel()
|
||||
{
|
||||
return this->_avgMicLevel;
|
||||
}
|
||||
|
||||
void ClientInputHandler::AddSampleToAverageMicLevel(uint8_t sampleValue)
|
||||
{
|
||||
this->_avgMicLevelTotal += (float)( (MIC_NULL_SAMPLE_VALUE > sampleValue) ? MIC_NULL_SAMPLE_VALUE - sampleValue : sampleValue - MIC_NULL_SAMPLE_VALUE );
|
||||
this->_avgMicLevelsRead += 1.0f;
|
||||
this->_avgMicLevel = this->_avgMicLevelTotal / this->_avgMicLevelsRead;
|
||||
}
|
||||
|
||||
void ClientInputHandler::ClearAverageMicLevel()
|
||||
{
|
||||
this->_avgMicLevelTotal = 0.0f;
|
||||
this->_avgMicLevelsRead = 0.0f;
|
||||
this->_avgMicLevel = 0.0f;
|
||||
}
|
||||
|
||||
bool ClientInputHandler::IsMicrophoneIdle()
|
||||
{
|
||||
return (this->_avgMicLevel < MIC_NULL_LEVEL_THRESHOLD);
|
||||
}
|
||||
|
||||
bool ClientInputHandler::IsMicrophoneClipping()
|
||||
{
|
||||
return (this->_avgMicLevel >= MIC_CLIP_LEVEL_THRESHOLD);
|
||||
}
|
||||
|
||||
AudioGenerator* ClientInputHandler::GetClientSoftwareMicSampleGenerator()
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexInputsPending);
|
||||
|
@ -287,6 +325,23 @@ void ClientInputHandler::SetClientSelectedAudioFileGenerator(AudioSampleBlockGen
|
|||
pthread_mutex_unlock(&this->_mutexInputsPending);
|
||||
}
|
||||
|
||||
void ClientInputHandler::SetClientHardwareMicSampleGeneratorApplied(AudioGenerator *hwGenerator)
|
||||
{
|
||||
if (hwGenerator == NULL)
|
||||
{
|
||||
this->_hardwareMicSampleGenerator = this->_nullSampleGenerator;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->_hardwareMicSampleGenerator = hwGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
AudioGenerator* ClientInputHandler::GetClientHardwareMicSampleGeneratorApplied()
|
||||
{
|
||||
return this->_hardwareMicSampleGenerator;
|
||||
}
|
||||
|
||||
bool ClientInputHandler::GetClientSoftwareMicState()
|
||||
{
|
||||
pthread_mutex_lock(&this->_mutexInputsPending);
|
||||
|
@ -611,3 +666,73 @@ void ClientInputHandler::ApplyInputs()
|
|||
FCEUMOV_HandleRecording();
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientInputHandler::IsHardwareMicAvailable()
|
||||
{
|
||||
// Do nothing. This is implementation-dependent.
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClientInputHandler::ResetHardwareMic()
|
||||
{
|
||||
this->ClearAverageMicLevel();
|
||||
this->ReportAverageMicLevel();
|
||||
|
||||
this->_hardwareMicSampleGenerator->resetSamples();
|
||||
}
|
||||
|
||||
uint8_t ClientInputHandler::HandleMicSampleRead()
|
||||
{
|
||||
uint8_t theSample = MIC_NULL_SAMPLE_VALUE;
|
||||
AudioGenerator *sampleGenerator = (this->GetClientSoftwareMicStateApplied()) ? this->GetClientSoftwareMicSampleGeneratorApplied() : this->_hardwareMicSampleGenerator;
|
||||
|
||||
theSample = sampleGenerator->generateSample();
|
||||
|
||||
this->AddSampleToAverageMicLevel(theSample);
|
||||
return theSample;
|
||||
}
|
||||
|
||||
void ClientInputHandler::ReportAverageMicLevel()
|
||||
{
|
||||
// Do nothing. This is implementation-dependent.
|
||||
// This method mainly exists for implementations to do some stuff during the
|
||||
// emulation loop.
|
||||
}
|
||||
|
||||
bool ClientInputHandler::GetHardwareMicMute()
|
||||
{
|
||||
return this->_isHardwareMicMuted;
|
||||
}
|
||||
|
||||
void ClientInputHandler::SetHardwareMicMute(bool muteState)
|
||||
{
|
||||
this->_isHardwareMicMuted = muteState;
|
||||
|
||||
if (muteState)
|
||||
{
|
||||
this->_hardwareMicSampleGenerator->resetSamples();
|
||||
this->ClearAverageMicLevel();
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientInputHandler::GetHardwareMicPause()
|
||||
{
|
||||
return this->_isHardwareMicPaused;
|
||||
}
|
||||
|
||||
void ClientInputHandler::SetHardwareMicPause(bool pauseState)
|
||||
{
|
||||
this->_isHardwareMicPaused = pauseState;
|
||||
}
|
||||
|
||||
float ClientInputHandler::GetHardwareMicNormalizedGain()
|
||||
{
|
||||
// Do nothing. This is implementation-dependent.
|
||||
// The default value is 0.0f, which represents 0.0% of the hardware device's pickup sensitivity.
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void ClientInputHandler::SetHardwareMicGainAsNormalized(float normalizedGain)
|
||||
{
|
||||
// Do nothing. This is implementation-dependent.
|
||||
}
|
||||
|
|
|
@ -330,6 +330,8 @@ protected:
|
|||
SineWaveGenerator *_sineWaveGenerator;
|
||||
AudioSampleBlockGenerator *_selectedAudioFileGenerator;
|
||||
|
||||
AudioGenerator *_hardwareMicSampleGenerator;
|
||||
|
||||
ClientInput _clientInputPending[NDSInputID_InputCount];
|
||||
ClientInput _clientInputProcessing[NDSInputID_InputCount];
|
||||
ClientInput _clientInputApplied[NDSInputID_InputCount];
|
||||
|
@ -354,6 +356,12 @@ protected:
|
|||
int16_t _paddleValueApplied;
|
||||
int16_t _paddleAdjustApplied;
|
||||
|
||||
float _avgMicLevel;
|
||||
float _avgMicLevelTotal;
|
||||
float _avgMicLevelsRead;
|
||||
bool _isHardwareMicMuted;
|
||||
bool _isHardwareMicPaused;
|
||||
|
||||
pthread_mutex_t _mutexInputsPending;
|
||||
|
||||
public:
|
||||
|
@ -374,11 +382,21 @@ public:
|
|||
double GetSineWaveFrequency();
|
||||
void SetSineWaveFrequency(double freq);
|
||||
|
||||
float GetAverageMicLevel();
|
||||
void AddSampleToAverageMicLevel(uint8_t sampleValue);
|
||||
void ClearAverageMicLevel();
|
||||
|
||||
bool IsMicrophoneIdle();
|
||||
bool IsMicrophoneClipping();
|
||||
|
||||
AudioGenerator* GetClientSoftwareMicSampleGenerator();
|
||||
AudioGenerator* GetClientSoftwareMicSampleGeneratorApplied();
|
||||
AudioSampleBlockGenerator* GetClientSelectedAudioFileGenerator();
|
||||
void SetClientSelectedAudioFileGenerator(AudioSampleBlockGenerator *selectedAudioFileGenerator);
|
||||
|
||||
void SetClientHardwareMicSampleGeneratorApplied(AudioGenerator *hwGenerator);
|
||||
AudioGenerator* GetClientHardwareMicSampleGeneratorApplied();
|
||||
|
||||
bool GetClientSoftwareMicState();
|
||||
bool GetClientSoftwareMicStateApplied();
|
||||
void SetClientSoftwareMicState(bool pressedState, MicrophoneMode micMode);
|
||||
|
@ -395,6 +413,20 @@ public:
|
|||
|
||||
void ProcessInputs();
|
||||
void ApplyInputs();
|
||||
|
||||
virtual bool IsHardwareMicAvailable();
|
||||
virtual void ResetHardwareMic();
|
||||
virtual uint8_t HandleMicSampleRead();
|
||||
virtual void ReportAverageMicLevel();
|
||||
|
||||
virtual bool GetHardwareMicMute();
|
||||
virtual void SetHardwareMicMute(bool muteState);
|
||||
|
||||
virtual bool GetHardwareMicPause();
|
||||
virtual void SetHardwareMicPause(bool pauseState);
|
||||
|
||||
virtual float GetHardwareMicNormalizedGain();
|
||||
virtual void SetHardwareMicGainAsNormalized(float normalizedGain);
|
||||
};
|
||||
|
||||
#endif // _CLIENT_INPUT_HANDLER_H_
|
||||
|
|
|
@ -33,6 +33,21 @@ static const uint8_t noiseSample[NUM_INTERNAL_NOISE_SAMPLES] =
|
|||
0xF4, 0xE1, 0xBF, 0x9A, 0x71, 0x58, 0x5B, 0x5F, 0x62, 0xC2, 0x25, 0x05, 0x01, 0x01, 0x01, 0x01
|
||||
};
|
||||
|
||||
size_t AudioGenerator::resetSamples()
|
||||
{
|
||||
// Do nothing. This is implementation-dependent.
|
||||
//
|
||||
// The return value represents the number of samples that were dropped.
|
||||
// By default, return 0 to signify that no samples are dropped. In other
|
||||
// words, all samples will continue to exist after the reset.
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t AudioGenerator::generateSample()
|
||||
{
|
||||
return MIC_NULL_SAMPLE_VALUE;
|
||||
}
|
||||
|
||||
size_t AudioGenerator::generateSampleBlock(size_t sampleCount, uint8_t *outBuffer)
|
||||
{
|
||||
if (outBuffer == NULL)
|
||||
|
@ -48,11 +63,6 @@ size_t AudioGenerator::generateSampleBlock(size_t sampleCount, uint8_t *outBuffe
|
|||
return sampleCount;
|
||||
}
|
||||
|
||||
uint8_t AudioGenerator::generateSample()
|
||||
{
|
||||
return MIC_NULL_SAMPLE_VALUE;
|
||||
}
|
||||
|
||||
AudioSampleBlockGenerator::AudioSampleBlockGenerator(const uint8_t *audioBuffer, const size_t sampleCount)
|
||||
{
|
||||
_buffer = (uint8_t *)malloc(sampleCount * sizeof(uint8_t));
|
||||
|
|
|
@ -28,8 +28,9 @@ public:
|
|||
AudioGenerator() {};
|
||||
virtual ~AudioGenerator() {};
|
||||
|
||||
virtual size_t generateSampleBlock(size_t sampleCount, uint8_t *outBuffer);
|
||||
virtual size_t resetSamples();
|
||||
virtual uint8_t generateSample();
|
||||
virtual size_t generateSampleBlock(size_t sampleCount, uint8_t *outBuffer);
|
||||
};
|
||||
|
||||
class NullGenerator : public AudioGenerator {};
|
||||
|
|
|
@ -870,7 +870,6 @@ volatile bool execute = true;
|
|||
[self setMasterExecute:YES];
|
||||
[self restoreCoreState];
|
||||
[[self cdsController] reset];
|
||||
[[self cdsController] updateMicLevel];
|
||||
}
|
||||
|
||||
- (void) getTimedEmulatorStatistics:(NSTimer *)timer
|
||||
|
@ -1159,6 +1158,10 @@ static void* RunCoreThread(void *arg)
|
|||
NDSError ndsError = NDS_GetLastError();
|
||||
pthread_mutex_unlock(¶m->mutexThreadExecute);
|
||||
|
||||
inputHandler->SetHardwareMicPause(true);
|
||||
inputHandler->ClearAverageMicLevel();
|
||||
inputHandler->ReportAverageMicLevel();
|
||||
|
||||
[cdsCore postNDSError:ndsError];
|
||||
continue;
|
||||
}
|
||||
|
@ -1167,9 +1170,8 @@ static void* RunCoreThread(void *arg)
|
|||
// of whether the NDS actually reads the mic or not.
|
||||
if ((ndsFrameInfo.frameIndex & 0x07) == 0x07)
|
||||
{
|
||||
CocoaDSController *cdsController = [cdsCore cdsController];
|
||||
[cdsController updateMicLevel];
|
||||
[cdsController clearMicLevelMeasure];
|
||||
inputHandler->ReportAverageMicLevel();
|
||||
inputHandler->ClearAverageMicLevel();
|
||||
}
|
||||
|
||||
const uint8_t framesToSkip = execControl->GetFramesToSkip();
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <libkern/OSAtomic.h>
|
||||
#include <vector>
|
||||
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
@class CocoaDSController;
|
||||
class ClientInputHandler;
|
||||
class CoreAudioInput;
|
||||
|
@ -45,16 +47,7 @@ class AudioSampleBlockGenerator;
|
|||
ClientInputHandler *inputHandler;
|
||||
|
||||
NSInteger stylusPressure;
|
||||
|
||||
float micLevel;
|
||||
float _micLevelTotal;
|
||||
float _micLevelsRead;
|
||||
|
||||
BOOL hardwareMicMute;
|
||||
size_t _availableMicSamples;
|
||||
|
||||
CoreAudioInput *CAInputDevice;
|
||||
|
||||
|
||||
NSString *hardwareMicInfoString;
|
||||
NSString *hardwareMicNameString;
|
||||
NSString *hardwareMicManufacturerString;
|
||||
|
@ -70,13 +63,9 @@ class AudioSampleBlockGenerator;
|
|||
@property (readonly) BOOL isHardwareMicIdle;
|
||||
@property (readonly) BOOL isHardwareMicInClip;
|
||||
@property (assign) float micLevel;
|
||||
@property (assign) BOOL hardwareMicEnabled;
|
||||
@property (readonly) BOOL hardwareMicLocked;
|
||||
@property (assign) float hardwareMicGain;
|
||||
@property (assign) BOOL hardwareMicMute;
|
||||
@property (assign) BOOL hardwareMicPause;
|
||||
@property (readonly) CoreAudioInput *CAInputDevice;
|
||||
@property (readonly) AudioGenerator *softwareMicSampleGenerator;
|
||||
@property (assign) AudioSampleBlockGenerator *selectedAudioFileGenerator;
|
||||
@property (retain) NSString *hardwareMicInfoString;
|
||||
@property (retain) NSString *hardwareMicNameString;
|
||||
|
@ -91,10 +80,8 @@ class AudioSampleBlockGenerator;
|
|||
- (void) setSineWaveGeneratorFrequency:(const double)freq;
|
||||
- (void) clearAutohold;
|
||||
- (void) reset;
|
||||
- (void) startHardwareMicDevice;
|
||||
|
||||
- (void) clearMicLevelMeasure;
|
||||
- (void) updateMicLevel;
|
||||
- (uint8_t) handleMicSampleRead:(CoreAudioInput *)caInput softwareMic:(AudioGenerator *)sampleGenerator;
|
||||
- (void) handleMicHardwareStateChanged:(CoreAudioInputDeviceInfo *)deviceInfo
|
||||
isEnabled:(BOOL)isHardwareEnabled
|
||||
isLocked:(BOOL)isHardwareLocked;
|
||||
|
@ -102,6 +89,33 @@ class AudioSampleBlockGenerator;
|
|||
|
||||
@end
|
||||
|
||||
class MacInputHandler : public ClientInputHandler
|
||||
{
|
||||
private:
|
||||
CocoaDSController *_cdsController;
|
||||
CoreAudioInput *_CAInputDevice;
|
||||
|
||||
public:
|
||||
MacInputHandler();
|
||||
~MacInputHandler();
|
||||
|
||||
CocoaDSController* GetCocoaController();
|
||||
void SetCocoaController(CocoaDSController *theController);
|
||||
|
||||
void StartHardwareMicDevice();
|
||||
|
||||
virtual bool IsHardwareMicAvailable();
|
||||
virtual void ReportAverageMicLevel();
|
||||
|
||||
virtual void SetHardwareMicMute(bool muteState);
|
||||
|
||||
virtual bool GetHardwareMicPause();
|
||||
virtual void SetHardwareMicPause(bool pauseState);
|
||||
|
||||
virtual float GetHardwareMicNormalizedGain();
|
||||
virtual void SetHardwareMicGainAsNormalized(float normalizedGain);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
#include "../../slot2.h"
|
||||
#undef BOOL
|
||||
|
||||
#include "ClientInputHandler.h"
|
||||
|
||||
|
||||
@implementation CocoaDSController
|
||||
|
||||
|
@ -39,14 +37,10 @@
|
|||
@dynamic isHardwareMicAvailable;
|
||||
@dynamic isHardwareMicIdle;
|
||||
@dynamic isHardwareMicInClip;
|
||||
@synthesize micLevel;
|
||||
@dynamic hardwareMicEnabled;
|
||||
@dynamic hardwareMicLocked;
|
||||
@dynamic micLevel;
|
||||
@dynamic hardwareMicGain;
|
||||
@synthesize hardwareMicMute;
|
||||
@dynamic hardwareMicMute;
|
||||
@dynamic hardwareMicPause;
|
||||
@synthesize CAInputDevice;
|
||||
@dynamic softwareMicSampleGenerator;
|
||||
@dynamic selectedAudioFileGenerator;
|
||||
@synthesize hardwareMicInfoString;
|
||||
@synthesize hardwareMicNameString;
|
||||
|
@ -62,32 +56,20 @@
|
|||
}
|
||||
|
||||
delegate = nil;
|
||||
inputHandler = new ClientInputHandler;
|
||||
_availableMicSamples = 0;
|
||||
|
||||
micLevel = 0.0f;
|
||||
_micLevelTotal = 0.0f;
|
||||
_micLevelsRead = 0.0f;
|
||||
|
||||
CAInputDevice = new CoreAudioInput;
|
||||
CAInputDevice->SetCallbackHardwareStateChanged(&CAHardwareStateChangedCallback, self, NULL);
|
||||
CAInputDevice->SetCallbackHardwareGainChanged(&CAHardwareGainChangedCallback, self, NULL);
|
||||
|
||||
|
||||
hardwareMicInfoString = @"No hardware input detected.";
|
||||
hardwareMicNameString = @"No hardware input detected.";
|
||||
hardwareMicManufacturerString = @"No hardware input detected.";
|
||||
hardwareMicSampleRateString = @"No hardware input detected.";
|
||||
|
||||
Mic_SetResetCallback(&CAResetCallback, self, NULL);
|
||||
Mic_SetSampleReadCallback(&CASampleReadCallback, self, NULL);
|
||||
inputHandler = new MacInputHandler;
|
||||
((MacInputHandler *)inputHandler)->SetCocoaController(self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
delete CAInputDevice;
|
||||
|
||||
[self setDelegate:nil];
|
||||
[self setHardwareMicInfoString:nil];
|
||||
[self setHardwareMicNameString:nil];
|
||||
|
@ -104,62 +86,66 @@
|
|||
|
||||
- (BOOL) isHardwareMicAvailable
|
||||
{
|
||||
return ( CAInputDevice->IsHardwareEnabled() &&
|
||||
!CAInputDevice->IsHardwareLocked() &&
|
||||
!CAInputDevice->GetPauseState() ) ? YES : NO;
|
||||
return (inputHandler->IsHardwareMicAvailable()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL) isHardwareMicIdle
|
||||
{
|
||||
return (micLevel < MIC_NULL_LEVEL_THRESHOLD);
|
||||
return (inputHandler->IsMicrophoneIdle()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL) isHardwareMicInClip
|
||||
{
|
||||
return (micLevel >= MIC_CLIP_LEVEL_THRESHOLD);
|
||||
return (inputHandler->IsMicrophoneClipping()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setHardwareMicEnabled:(BOOL)micEnabled
|
||||
- (void) setMicLevel:(float)micLevelValue
|
||||
{
|
||||
if (micEnabled)
|
||||
// This method doesn't set the mic level, since the mic level is always an internally
|
||||
// calculated value. What this method actually does is trigger updates for any
|
||||
// KVO-compliant controls that are associated with this property.
|
||||
|
||||
if ( (delegate != nil) && [delegate respondsToSelector:@selector(doMicLevelUpdateFromController:)] )
|
||||
{
|
||||
CAInputDevice->Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
CAInputDevice->Stop();
|
||||
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
|
||||
[[self delegate] doMicLevelUpdateFromController:self];
|
||||
[tempPool release];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) hardwareMicEnabled
|
||||
- (float) micLevel
|
||||
{
|
||||
return (CAInputDevice->IsHardwareEnabled()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL) hardwareMicLocked
|
||||
{
|
||||
return (CAInputDevice->IsHardwareLocked()) ? YES : NO;
|
||||
return inputHandler->GetAverageMicLevel();
|
||||
}
|
||||
|
||||
- (void) setHardwareMicGain:(float)micGain
|
||||
{
|
||||
CAInputDevice->SetGain(micGain);
|
||||
inputHandler->SetHardwareMicGainAsNormalized(micGain);
|
||||
}
|
||||
|
||||
- (float) hardwareMicGain
|
||||
{
|
||||
return CAInputDevice->GetGain();
|
||||
return inputHandler->GetHardwareMicNormalizedGain();
|
||||
}
|
||||
|
||||
- (void) setHardwareMicMute:(BOOL)isMicMuted
|
||||
{
|
||||
inputHandler->SetHardwareMicMute((isMicMuted) ? true : false);
|
||||
}
|
||||
|
||||
- (BOOL) hardwareMicMute
|
||||
{
|
||||
return (inputHandler->GetHardwareMicMute()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setHardwareMicPause:(BOOL)isMicPaused
|
||||
{
|
||||
bool pauseState = (isMicPaused || [self hardwareMicMute]) ? true : false;
|
||||
CAInputDevice->SetPauseState(pauseState);
|
||||
inputHandler->SetHardwareMicPause((isMicPaused) ? true : false);
|
||||
}
|
||||
|
||||
- (BOOL) hardwareMicPause
|
||||
{
|
||||
return (CAInputDevice->GetPauseState()) ? YES : NO;
|
||||
return (inputHandler->GetHardwareMicPause()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void) setSoftwareMicState:(BOOL)theState mode:(NSInteger)micMode
|
||||
|
@ -172,11 +158,6 @@
|
|||
return (inputHandler->GetClientSoftwareMicState()) ? YES : NO;
|
||||
}
|
||||
|
||||
- (AudioGenerator *) softwareMicSampleGenerator
|
||||
{
|
||||
return inputHandler->GetClientSoftwareMicSampleGenerator();
|
||||
}
|
||||
|
||||
- (void) setSelectedAudioFileGenerator:(AudioSampleBlockGenerator *)audioGenerator
|
||||
{
|
||||
inputHandler->SetClientSelectedAudioFileGenerator(audioGenerator);
|
||||
|
@ -246,63 +227,13 @@
|
|||
- (void) reset
|
||||
{
|
||||
[self setAutohold:NO];
|
||||
[self setMicLevel:0.0f];
|
||||
[self clearMicLevelMeasure];
|
||||
|
||||
_availableMicSamples = 0;
|
||||
inputHandler->ResetHardwareMic();
|
||||
}
|
||||
|
||||
- (void) clearMicLevelMeasure
|
||||
- (void) startHardwareMicDevice
|
||||
{
|
||||
_micLevelTotal = 0.0f;
|
||||
_micLevelsRead = 0.0f;
|
||||
}
|
||||
|
||||
- (void) updateMicLevel
|
||||
{
|
||||
float avgMicLevel = (_micLevelsRead != 0) ? _micLevelTotal / _micLevelsRead : 0.0f;
|
||||
|
||||
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
|
||||
[self setMicLevel:avgMicLevel];
|
||||
|
||||
if (delegate != nil && [delegate respondsToSelector:@selector(doMicLevelUpdateFromController:)])
|
||||
{
|
||||
[[self delegate] doMicLevelUpdateFromController:self];
|
||||
}
|
||||
|
||||
[tempPool release];
|
||||
}
|
||||
|
||||
- (uint8_t) handleMicSampleRead:(CoreAudioInput *)caInput softwareMic:(AudioGenerator *)sampleGenerator
|
||||
{
|
||||
uint8_t theSample = MIC_NULL_SAMPLE_VALUE;
|
||||
|
||||
if (!inputHandler->GetClientSoftwareMicStateApplied() && (caInput != NULL))
|
||||
{
|
||||
if (caInput->GetPauseState())
|
||||
{
|
||||
return theSample;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_availableMicSamples == 0)
|
||||
{
|
||||
_availableMicSamples = CAInputDevice->Pull();
|
||||
}
|
||||
|
||||
caInput->_samplesConverted->read(&theSample, 1);
|
||||
theSample >>= 1; // Samples from CoreAudio are 8-bit, so we need to convert the sample to 7-bit
|
||||
_availableMicSamples--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
theSample = sampleGenerator->generateSample();
|
||||
}
|
||||
|
||||
_micLevelTotal += (float)( (MIC_NULL_SAMPLE_VALUE > theSample) ? MIC_NULL_SAMPLE_VALUE - theSample : theSample - MIC_NULL_SAMPLE_VALUE );
|
||||
_micLevelsRead += 1.0f;
|
||||
return theSample;
|
||||
((MacInputHandler *)inputHandler)->StartHardwareMicDevice();
|
||||
}
|
||||
|
||||
- (void) handleMicHardwareStateChanged:(CoreAudioInputDeviceInfo *)deviceInfo
|
||||
|
@ -329,10 +260,10 @@
|
|||
[self setHardwareMicSampleRateString:[NSString stringWithFormat:@"%1.1f Hz", (double)deviceInfo->sampleRate]];
|
||||
}
|
||||
|
||||
[self clearMicLevelMeasure];
|
||||
[self setMicLevel:0.0f];
|
||||
inputHandler->ClearAverageMicLevel();
|
||||
inputHandler->ReportAverageMicLevel();
|
||||
|
||||
if (delegate != nil && [delegate respondsToSelector:@selector(doMicHardwareStateChangedFromController:isEnabled:isLocked:)])
|
||||
if ( (delegate != nil) && [delegate respondsToSelector:@selector(doMicHardwareStateChangedFromController:isEnabled:isLocked:)] )
|
||||
{
|
||||
[[self delegate] doMicHardwareStateChangedFromController:self
|
||||
isEnabled:isHardwareEnabled
|
||||
|
@ -344,7 +275,7 @@
|
|||
|
||||
- (void) handleMicHardwareGainChanged:(float)gainValue
|
||||
{
|
||||
if (delegate != nil && [delegate respondsToSelector:@selector(doMicHardwareGainChangedFromController:gain:)])
|
||||
if ( (delegate != nil) && [delegate respondsToSelector:@selector(doMicHardwareGainChangedFromController:gain:)] )
|
||||
{
|
||||
NSAutoreleasePool *tempPool = [[NSAutoreleasePool alloc] init];
|
||||
[[self delegate] doMicHardwareGainChangedFromController:self gain:gainValue];
|
||||
|
@ -354,16 +285,105 @@
|
|||
|
||||
@end
|
||||
|
||||
MacInputHandler::MacInputHandler()
|
||||
{
|
||||
_cdsController = nil;
|
||||
_CAInputDevice = new CoreAudioInput;
|
||||
_hardwareMicSampleGenerator = _CAInputDevice;
|
||||
_isHardwareMicMuted = false;
|
||||
|
||||
_CAInputDevice->SetCallbackHardwareStateChanged(&CAHardwareStateChangedCallback, _cdsController, NULL);
|
||||
_CAInputDevice->SetCallbackHardwareGainChanged(&CAHardwareGainChangedCallback, _cdsController, NULL);
|
||||
|
||||
Mic_SetResetCallback(&CAResetCallback, _CAInputDevice, NULL);
|
||||
Mic_SetSampleReadCallback(&CASampleReadCallback, this, NULL);
|
||||
}
|
||||
|
||||
MacInputHandler::~MacInputHandler()
|
||||
{
|
||||
delete this->_CAInputDevice;
|
||||
}
|
||||
|
||||
CocoaDSController* MacInputHandler::GetCocoaController()
|
||||
{
|
||||
return this->_cdsController;
|
||||
}
|
||||
|
||||
void MacInputHandler::SetCocoaController(CocoaDSController *theController)
|
||||
{
|
||||
this->_cdsController = theController;
|
||||
this->_CAInputDevice->SetCallbackHardwareStateChanged(&CAHardwareStateChangedCallback, theController, NULL);
|
||||
this->_CAInputDevice->SetCallbackHardwareGainChanged(&CAHardwareGainChangedCallback, theController, NULL);
|
||||
}
|
||||
|
||||
void MacInputHandler::StartHardwareMicDevice()
|
||||
{
|
||||
this->_CAInputDevice->Start();
|
||||
}
|
||||
|
||||
bool MacInputHandler::IsHardwareMicAvailable()
|
||||
{
|
||||
return ( this->_CAInputDevice->IsHardwareEnabled() && !this->_CAInputDevice->IsHardwareLocked() );
|
||||
}
|
||||
|
||||
void MacInputHandler::ReportAverageMicLevel()
|
||||
{
|
||||
[this->_cdsController setMicLevel:this->GetAverageMicLevel()];
|
||||
}
|
||||
|
||||
void MacInputHandler::SetHardwareMicMute(bool muteState)
|
||||
{
|
||||
const bool needSetMuteState = (this->_isHardwareMicMuted != muteState);
|
||||
|
||||
if (needSetMuteState)
|
||||
{
|
||||
if (muteState)
|
||||
{
|
||||
this->_hardwareMicSampleGenerator->resetSamples();
|
||||
this->ClearAverageMicLevel();
|
||||
}
|
||||
|
||||
this->_isHardwareMicMuted = muteState;
|
||||
this->_CAInputDevice->SetPauseState(this->_isHardwareMicPaused || muteState);
|
||||
}
|
||||
}
|
||||
|
||||
bool MacInputHandler::GetHardwareMicPause()
|
||||
{
|
||||
return this->_CAInputDevice->GetPauseState();
|
||||
}
|
||||
|
||||
void MacInputHandler::SetHardwareMicPause(bool pauseState)
|
||||
{
|
||||
const bool needSetPauseState = (this->_isHardwareMicPaused != pauseState);
|
||||
|
||||
if (needSetPauseState)
|
||||
{
|
||||
this->_isHardwareMicPaused = pauseState;
|
||||
this->_CAInputDevice->SetPauseState(pauseState || this->_isHardwareMicMuted);
|
||||
}
|
||||
}
|
||||
|
||||
float MacInputHandler::GetHardwareMicNormalizedGain()
|
||||
{
|
||||
return this->_CAInputDevice->GetNormalizedGain();
|
||||
}
|
||||
|
||||
void MacInputHandler::SetHardwareMicGainAsNormalized(float normalizedGain)
|
||||
{
|
||||
this->_CAInputDevice->SetGainAsNormalized(normalizedGain);
|
||||
}
|
||||
|
||||
void CAResetCallback(void *inParam1, void *inParam2)
|
||||
{
|
||||
CocoaDSController *cdsController = (CocoaDSController *)inParam1;
|
||||
[cdsController CAInputDevice]->Start();
|
||||
CoreAudioInput *caInputDevice = (CoreAudioInput *)inParam1;
|
||||
caInputDevice->Start();
|
||||
}
|
||||
|
||||
uint8_t CASampleReadCallback(void *inParam1, void *inParam2)
|
||||
{
|
||||
CocoaDSController *cdsController = (CocoaDSController *)inParam1;
|
||||
return [cdsController handleMicSampleRead:[cdsController CAInputDevice] softwareMic:[cdsController softwareMicSampleGenerator]];
|
||||
ClientInputHandler *inputHandler = (ClientInputHandler *)inParam1;
|
||||
return inputHandler->HandleMicSampleRead();
|
||||
}
|
||||
|
||||
void CAHardwareStateChangedCallback(CoreAudioInputDeviceInfo *deviceInfo,
|
||||
|
|
|
@ -47,7 +47,7 @@ CoreAudioInput::CoreAudioInput()
|
|||
_hwDeviceInfo.deviceUID = CFSTR("");
|
||||
_hwDeviceInfo.modelUID = CFSTR("");
|
||||
_hwDeviceInfo.sampleRate = 0.0;
|
||||
_isPaused = false;
|
||||
_isPaused = true;
|
||||
_isHardwareEnabled = false;
|
||||
_isHardwareLocked = true;
|
||||
_captureFrames = 0;
|
||||
|
@ -602,12 +602,12 @@ void CoreAudioInput::SetPauseState(bool pauseState)
|
|||
this->_isPaused = (this->IsHardwareLocked()) ? true : pauseState;
|
||||
}
|
||||
|
||||
float CoreAudioInput::GetGain() const
|
||||
float CoreAudioInput::GetNormalizedGain() const
|
||||
{
|
||||
return this->_inputGainNormalized;
|
||||
}
|
||||
|
||||
void CoreAudioInput::SetGain(float normalizedGain)
|
||||
void CoreAudioInput::SetGainAsNormalized(float normalizedGain)
|
||||
{
|
||||
Float32 gainValue = normalizedGain;
|
||||
UInt32 gainPropSize = sizeof(gainValue);
|
||||
|
@ -698,6 +698,36 @@ void CoreAudioInput::UpdateHardwareLock()
|
|||
this->_hwStateChangedCallbackParam2);
|
||||
}
|
||||
|
||||
size_t CoreAudioInput::resetSamples()
|
||||
{
|
||||
size_t samplesToDrop = this->_samplesConverted->getUsedElements();
|
||||
this->_samplesConverted->clear();
|
||||
|
||||
return samplesToDrop;
|
||||
}
|
||||
|
||||
uint8_t CoreAudioInput::generateSample()
|
||||
{
|
||||
uint8_t theSample = MIC_NULL_SAMPLE_VALUE;
|
||||
|
||||
if (this->_isPaused)
|
||||
{
|
||||
return theSample;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->_samplesConverted->getUsedElements() == 0)
|
||||
{
|
||||
this->Pull();
|
||||
}
|
||||
|
||||
this->_samplesConverted->read(&theSample, 1);
|
||||
theSample >>= 1; // Samples from CoreAudio are 8-bit, so we need to convert the sample to 7-bit
|
||||
}
|
||||
|
||||
return theSample;
|
||||
}
|
||||
|
||||
void CoreAudioInput::SetCallbackHardwareStateChanged(CoreAudioInputHardwareStateChangedCallback callbackFunc, void *inParam1, void *inParam2)
|
||||
{
|
||||
this->_hwStateChangedCallbackFunc = callbackFunc;
|
||||
|
|
|
@ -22,8 +22,9 @@
|
|||
#include <AudioUnit/AudioUnit.h>
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#include "ringbuffer.h"
|
||||
|
||||
#include "ringbuffer.h"
|
||||
#include "audiosamplegenerator.h"
|
||||
|
||||
struct CoreAudioInputDeviceInfo
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ typedef void (*CoreAudioInputHardwareStateChangedCallback)(CoreAudioInputDeviceI
|
|||
|
||||
typedef void (*CoreAudioInputHardwareGainChangedCallback)(float normalizedGain, void *inParam1, void *inParam2);
|
||||
|
||||
class CoreAudioInput
|
||||
class CoreAudioInput : public AudioGenerator
|
||||
{
|
||||
private:
|
||||
OSSpinLock *_spinlockAUHAL;
|
||||
|
@ -65,6 +66,8 @@ private:
|
|||
AudioBufferList *_convertBufferList;
|
||||
UInt32 _captureFrames;
|
||||
|
||||
RingBuffer *_samplesConverted;
|
||||
|
||||
float _inputGainNormalized;
|
||||
AudioUnitElement _inputElement;
|
||||
|
||||
|
@ -80,10 +83,9 @@ public:
|
|||
AudioTimeStamp _timeStamp;
|
||||
AudioBufferList *_captureBufferList;
|
||||
RingBuffer *_samplesCaptured;
|
||||
RingBuffer *_samplesConverted;
|
||||
|
||||
CoreAudioInput();
|
||||
~CoreAudioInput();
|
||||
virtual ~CoreAudioInput();
|
||||
|
||||
void Start();
|
||||
void Stop();
|
||||
|
@ -93,13 +95,16 @@ public:
|
|||
bool IsHardwareLocked() const;
|
||||
bool GetPauseState() const;
|
||||
void SetPauseState(bool pauseState);
|
||||
float GetGain() const;
|
||||
void SetGain(float normalizedGain);
|
||||
float GetNormalizedGain() const;
|
||||
void SetGainAsNormalized(float normalizedGain);
|
||||
|
||||
void UpdateHardwareGain(float normalizedGain);
|
||||
void UpdateHardwareLock();
|
||||
void SetCallbackHardwareStateChanged(CoreAudioInputHardwareStateChangedCallback callbackFunc, void *inParam1, void *inParam2);
|
||||
void SetCallbackHardwareGainChanged(CoreAudioInputHardwareGainChangedCallback callbackFunc, void *inParam1, void *inParam2);
|
||||
|
||||
virtual size_t resetSamples();
|
||||
virtual uint8_t generateSample();
|
||||
};
|
||||
|
||||
class CoreAudioOutput
|
||||
|
|
|
@ -810,7 +810,6 @@
|
|||
const BOOL muteState = [CocoaDSUtil getIBActionSenderButtonStateBool:sender];
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
|
||||
[[cdsCore cdsController] setHardwareMicMute:muteState];
|
||||
[[cdsCore cdsController] setHardwareMicPause:([cdsCore coreState] != ExecutionBehavior_Run)];
|
||||
[self updateMicStatusIcon];
|
||||
}
|
||||
|
||||
|
@ -1911,7 +1910,6 @@
|
|||
|
||||
[cdsCore setSlot1StatusText:NSSTRING_STATUS_EMULATION_NOT_RUNNING];
|
||||
[[cdsCore cdsController] reset];
|
||||
[[cdsCore cdsController] updateMicLevel];
|
||||
|
||||
result = YES;
|
||||
|
||||
|
@ -2016,7 +2014,11 @@
|
|||
{
|
||||
if ([cdsController isHardwareMicAvailable])
|
||||
{
|
||||
if ([cdsController isHardwareMicInClip])
|
||||
if ([cdsController hardwareMicPause])
|
||||
{
|
||||
micIcon = iconMicDisabled;
|
||||
}
|
||||
else if ([cdsController isHardwareMicInClip])
|
||||
{
|
||||
micIcon = iconMicInClip;
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
|
||||
// Init the DS controller.
|
||||
[[newCore cdsController] setDelegate:emuControl];
|
||||
[[newCore cdsController] setHardwareMicEnabled:YES];
|
||||
[[newCore cdsController] startHardwareMicDevice];
|
||||
|
||||
// Init the DS speakers.
|
||||
CocoaDSSpeaker *newSpeaker = [[[CocoaDSSpeaker alloc] init] autorelease];
|
||||
|
@ -207,7 +207,6 @@
|
|||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
CocoaDSCore *cdsCore = (CocoaDSCore *)[cdsCoreController content];
|
||||
EmuControllerDelegate *emuControl = (EmuControllerDelegate *)[emuControlController content];
|
||||
|
||||
// Determine if the app was run for the first time.
|
||||
|
@ -237,11 +236,10 @@
|
|||
[[inputPrefsView inputPrefOutlineView] expandItem:nil expandChildren:YES];
|
||||
[[inputPrefsView inputProfileMenu] selectItemAtIndex:0];
|
||||
|
||||
// Make sure that the mic is paused to start with.
|
||||
[[cdsCore cdsController] setHardwareMicPause:YES];
|
||||
// Initialize the microphone status icon.
|
||||
[emuControl updateMicStatusIcon];
|
||||
|
||||
//Bring the application to the front
|
||||
// Bring the application to the front
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
[self restoreDisplayWindowStates];
|
||||
|
||||
|
|
Loading…
Reference in New Issue