Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion Input/MicStreamSelector/Source/MicStreamSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,23 @@ static char filepath_char[MAX_PATH]; // stores the fu
static std::queue<Windows::Media::AudioFrame^> audioqueue; // stores our microphone data to hand back to the app

// error codes to hand back to engine with nice printed output
private enum ErrorCodes { ALREADY_RUNNING = -10, NO_AUDIO_DEVICE, NO_INPUT_DEVICE, ALREADY_RECORDING, GRAPH_NOT_EXIST, CHANNEL_COUNT_MISMATCH, FILE_CREATION_PERMISSION_ERROR, NOT_ENOUGH_DATA, NEED_ENABLED_MIC_CAPABILITY };
private enum ErrorCodes { ALREADY_PAUSED = -15, ALREADY_RESUMED = -14, ALREADY_STREAMING = -13, NOT_STREAMING = -12, NOT_RUNNING = -11, ALREADY_RUNNING = -10, NO_AUDIO_DEVICE, NO_INPUT_DEVICE, ALREADY_RECORDING, GRAPH_NOT_EXIST, CHANNEL_COUNT_MISMATCH, FILE_CREATION_PERMISSION_ERROR, NOT_ENOUGH_DATA, NEED_ENABLED_MIC_CAPABILITY };

bool initialized;
bool recording;
bool streaming;
bool paused;
int appExpectedBufferLength;
int dataInBuffer;
int samplesPerQuantum; // preferred sample size per chunk of data from the audio driver. usually you want system default.
int numChannels;
int indexInFrame; // keeps track of copying data out of the plug-in and into the application

void resetToDefaults() { // used on init to reset state of the plug-in
initialized = false;
recording = false;
streaming = false;
paused = false;
appExpectedBufferLength = -1; // By making negative, we won't output data until we get at least one app call.
dataInBuffer = 0;
samplesPerQuantum = 256;
Expand Down Expand Up @@ -204,6 +210,8 @@ extern "C"
// Make a callback at the end of every frame to store our data until the app wants it.
graph->QuantumProcessed += ref new Windows::Foundation::TypedEventHandler<Windows::Media::Audio::AudioGraph ^, Platform::Object ^>(&OnQuantumProcessed);

initialized = true;

return 0;
}

Expand All @@ -224,6 +232,10 @@ extern "C"

API int MicStartStream(bool keepData, bool previewOnDevice, CallbackIntoHost cb)
{
if (streaming)
{
return ErrorCodes::ALREADY_STREAMING;
}
if (!graph)
{
int err = MicInitializeDefault(0);
Expand All @@ -243,17 +255,23 @@ extern "C"
}
hostCallback = cb;
graph->Start();
streaming = true;
return 0;
}

API int MicStopStream()
{
if (!streaming)
{
return ErrorCodes::NOT_STREAMING;
}
if (!graph)
{
return ErrorCodes::GRAPH_NOT_EXIST;
}
graph->Stop();
hostCallback = nullptr;
streaming = false;
return 0;
}

Expand Down Expand Up @@ -384,20 +402,30 @@ extern "C"
}

API int MicPause() {
if (paused)
{
return ErrorCodes::ALREADY_PAUSED;
}
if (!graph)
{
return ErrorCodes::GRAPH_NOT_EXIST;
}
graph->Stop();
paused = true;
return 0;
}

API int MicResume() {
if (!paused)
{
return ErrorCodes::ALREADY_RESUMED;
}
if (!graph)
{
return ErrorCodes::GRAPH_NOT_EXIST;
}
graph->Start();
paused = false;
return 0;
}

Expand All @@ -415,6 +443,10 @@ extern "C"

API int MicDestroy()
{
if (!initialized)
{
return ErrorCodes::NOT_RUNNING;
}
if (!graph) // If there isn't a graph, there is nothing to stop, so just return
{
return ErrorCodes::GRAPH_NOT_EXIST;
Expand Down Expand Up @@ -443,6 +475,7 @@ extern "C"
#ifdef MEMORYLEAKDETECT
_CrtDumpMemoryLeaks(); // output our memory stats if desired
#endif // MEMORYLEAKDETECT
initialized = false;
return 0;
}

Expand Down
79 changes: 47 additions & 32 deletions Input/MicStreamSelector/UnityAddon/WindowsMicrophoneStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,20 @@ public float Gain
/// Initializes the microphone stream.
/// </summary>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode Initialize(WindowsMicrophoneStreamType streamType)
{
if (initialized)
{
// The microphone stream is already initialized, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.AlreadyRunning;
}

return (WindowsMicrophoneStreamErrorCode)MicInitializeCustomRate((int)streamType, AudioSettings.outputSampleRate);
initialized = true;

return (WindowsMicrophoneStreamErrorCode)MicInitializeCustomRate((int)streamType, AudioSettings.outputSampleRate);
}

private bool paused = false;
Expand All @@ -111,17 +113,19 @@ public WindowsMicrophoneStreamErrorCode Initialize(WindowsMicrophoneStreamType s
/// Pauses the microphone stream.
/// </summary>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode Pause()
{
if (paused)
{
// The microphone stream is already paused, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.AlreadyPaused;
}

paused = true;

return (WindowsMicrophoneStreamErrorCode)MicPause();
}

Expand All @@ -131,8 +135,9 @@ public WindowsMicrophoneStreamErrorCode Pause()
/// <param name="buffer"/>The buffer in which to plce the data.</param>
/// <param name="numChannels">The number of audio channels to read.</param>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode ReadAudioFrame(float[] buffer, int numChannels)
{
Expand All @@ -143,17 +148,19 @@ public WindowsMicrophoneStreamErrorCode ReadAudioFrame(float[] buffer, int numCh
/// Resumes the microphone stream
/// </summary>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode Resume()
{
if (!paused)
{
// The microphone stream is already resumed, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.AlreadyResumed;
}

paused = false;

return (WindowsMicrophoneStreamErrorCode)MicResume();
}

Expand All @@ -168,8 +175,9 @@ public WindowsMicrophoneStreamErrorCode Resume()
/// audio device.
/// </param>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
/// <remarks>
/// Files are created in the Music Library folder.
Expand All @@ -178,10 +186,11 @@ public WindowsMicrophoneStreamErrorCode StartRecording(string fileName, bool pre
{
if (recording)
{
// The microphone stream is already recording, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.AlreadyRecording;
}

recording = true;

return (WindowsMicrophoneStreamErrorCode)MicStartRecording(fileName, preview);
}

Expand All @@ -199,8 +208,9 @@ public WindowsMicrophoneStreamErrorCode StartRecording(string fileName, bool pre
/// audio device.
/// </param>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
/// <remarks>
/// When keepData is set to false, the application will always receive the latest
Expand All @@ -211,10 +221,11 @@ public WindowsMicrophoneStreamErrorCode StartStream(bool keepData, bool preview)
{
if (streaming)
{
// The microphone stream is already streaming, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.AlreadyStreaming;
}

streaming = true;

return (WindowsMicrophoneStreamErrorCode)MicStartStream(keepData, preview);
}

Expand All @@ -241,35 +252,39 @@ public string StopRecording()
/// Stops the microphone stream.
/// </summary>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode StopStream()
{
if (!streaming)
{
// The microphone stream is already stopped, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.NotStreaming;
}

streaming = false;

return (WindowsMicrophoneStreamErrorCode)MicStopStream();
}

/// <summary>
/// Uninitializes the microphone stream.
/// </summary>
/// <returns>
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success or the
/// reason that the call failed.
/// A <see cref="WindowsMicrophoneStreamErrorCode"/> value indicating success, the
/// reason that the call failed or the reason why the method did not continue past
/// the if-statement check.
/// </returns>
public WindowsMicrophoneStreamErrorCode Uninitialize()
{
if (!initialized)
{
// The microphone stream is not initialized, no need to alarm the calling code.
return WindowsMicrophoneStreamErrorCode.Success;
return WindowsMicrophoneStreamErrorCode.NotRunning;
}

initialized = false;

return (WindowsMicrophoneStreamErrorCode)MicDestroy();
}

Expand Down Expand Up @@ -312,4 +327,4 @@ public WindowsMicrophoneStreamErrorCode Uninitialize()
}

#endif // UNITY_STANDALONE_WIN || UNITY_WSA || UNITY_EDITOR_WIN
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,31 @@ public enum WindowsMicrophoneStreamErrorCode
/// </summary>
Success = 0,

/// <summary>
/// The microphone stream has already been paused.
/// </summary>
AlreadyPaused = -15,

/// <summary>
/// The microphone stream has already been resumed.
/// </summary>
AlreadyResumed = -14,

/// <summary>
/// The microphone stream has already been started.
/// </summary>
AlreadyStreaming = -13,

/// <summary>
/// The microphone stream has already been stopped.
/// </summary>
NotStreaming = -12,

/// <summary>
/// The microphone is already uninitialized.
/// </summary>
NotRunning = -11,

/// <summary>
/// The microphone has already been initialized.
/// </summary>
Expand Down Expand Up @@ -58,4 +83,4 @@ public enum WindowsMicrophoneStreamErrorCode
/// </summary>
NeedMicCapabilityEnabled
}
}
}