Cocoa Port: Refactor the hardware mic stuff out of CocoaDSController and into ClientInputHandler.

This commit is contained in:
rogerman 2017-09-21 00:33:28 -07:00
parent f8bbbec0ae
commit f521ab1164
11 changed files with 398 additions and 159 deletions

View File

@ -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.
}

View File

@ -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_

View File

@ -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));

View File

@ -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 {};

View File

@ -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(&param->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();

View File

@ -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"
{

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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];