singe/src/mic.h

98 lines
3.9 KiB
C

/*
*
* Singe 3
* Copyright (C) 2006-2026 Scott Duensing <scott@kangaroopunch.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#ifndef MIC_H
#define MIC_H
#include <stdbool.h>
#include <stdint.h>
// The microphone: one recording device at a time, heard as mono float samples at MIC_RATE. SDL's
// stream callback keeps the newest of them in a ring, with the level of each block; everything a
// game asks is answered from that ring on the engine's thread (PLAN.md section 62).
#define MIC_RATE 48000 // Opus's native rate, so a voice frame needs no resampling
#define MIC_LATENCY_UNKNOWN -1 // micLatency before any calibration has finished
#define MIC_LATENCY_MAX 1000 // A measured latency longer than this is not believed
#define MIC_RING_SECONDS 8 // The newest this much is kept; a slower reader loses the rest
typedef enum MicCalibrationE {
MIC_CALIBRATION_IDLE = 0, // Nothing asked, or the last one finished
MIC_CALIBRATION_RUNNING = 1,
MIC_CALIBRATION_DONE = 2, // micLatency holds the answer
MIC_CALIBRATION_FAILED = 3 // The clicks were never heard back
} MicCalibrationE;
// Starts a latency measurement: clicks played through the speakers and timed coming back through
// the microphone. False when no microphone is open or the speakers cannot be opened.
bool micCalibrate(void);
MicCalibrationE micCalibrationState(void);
void micClose(void);
// The recording devices SDL can see, and each one's name (NULL when the index names none). The
// list is taken afresh by micDeviceCount.
int32_t micDeviceCount(void);
const char *micDeviceName(int32_t index);
bool micIsOpen(void);
// The milliseconds between a sound being made and the game hearing it, or MIC_LATENCY_UNKNOWN.
int32_t micLatency(void);
// RMS and peak of the last block heard, 0 to 1.
void micLevel(float *rms, float *peak);
// Plays what the microphone hears through the speakers, at volume 0 to 1. Off by default.
bool micMonitor(bool on, float volume);
// Opens a recording device by name, or the default for NULL. Closes one already open.
bool micOpen(const char *name);
// The fundamental of what was heard most recently, in Hz, and how clearly periodic it is, 0 to 1;
// 0 Hz when nothing voiced is there.
void micPitch(float *hz, float *clarity);
void micQuit(void);
// Up to max samples heard since the last read, as 16-bit, oldest first. Returns how many. A reader
// that falls a whole ring behind skips to the oldest still kept.
int32_t micRead(int16_t *out, int32_t max);
// Writes everything heard from now on to a 16-bit mono WAV file at path, until micRecordStop.
bool micRecordStart(const char *path);
void micRecordStop(void);
// Sets the latency a game already knows (from the machine settings), MIC_LATENCY_UNKNOWN to forget.
void micSetLatency(int32_t milliseconds);
// Once a frame on the engine's thread: the recording written, the calibration stepped. True on the
// frame a calibration finishes with an answer, so the caller can keep it.
bool micUpdate(void);
#endif // MIC_H