草庐IT

c++ - 以编程方式增加麦克风增益

coder 2024-02-25 原文

我正在尝试为 VOIP 场景增加麦克风的增益。 我正在使用 PortAudio 获取输入流(带有 paFloat32 类型的样本),我将这些值乘以 float ,然后将结果流传递到输出设备。 注意:我将它传递给自动重定向到虚拟输入设备(程序:VB-Cable)的虚拟输出设备,VOIP 应用程序可以将其用作麦克风输入并应用增益。

我想知道是否有更好的方法来增加信号的增益以更好地保持质量。

我读到,执行此类增益计算的方法是,首先将输入转换为更高精度的格式,以这种格式执行增益乘法,应用裁剪,然后再转换回原始格式,这样会更好。 我不确定如何使用 PortAudio 的 paFloat32 类型执行此操作,我已经在源代码中包含了我的尝试注释掉。当我启用它时,即使增益设置为 1,也会出现明显的噪音问题。

依赖:tinycon, PortAudio

编译:g++ main.cpp tinycon.cpp -o main -L./-lcygportaudio-2 -lrt -lm -pthread -std=c++11

代码:

#include "portaudio.h"
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include "tinycon.h"

#define SAMPLE_RATE       (44100)
#define FRAMES_PER_BUFFER   (441)
#define DITHER_FLAG           (1)

#define PA_SAMPLE_TYPE  paFloat32
#define SAMPLE_SIZE (4)
#define SAMPLE_SILENCE  (0)
#define PRINTF_S_FORMAT "%f"

/*******************************************************************/
double multiplier = 1.0;
double multiplierStep = 0.1;
int main(int argc, char **argv);
int xrun(PaStream *stream, int err, char* sampleBlock);
void error1(PaStream *stream, char* sampleBlock);
void error2(PaStream *stream, int err);
void listDevices();

// Use tinycon and a second thread for non blocking input
class tcon : public tinyConsole
{
public:
        tcon (std::string s): tinyConsole(s) {;}

        int hotkeys(char c)
        {
                if (c == 's') {
                        if (multiplier >= (0+multiplierStep)) {
                                multiplier -= multiplierStep;
                        }
                        printf( "Multiplier: %f\n", multiplier );
                        return 1;
                }
                if (c == 'w') {
                        multiplier += multiplierStep;
                        printf( "Multiplier: %f\n", multiplier );
                        return 1;
                }
                return 0;
        }
};
int inputThread() {
        tcon tc (std::string(""));
        tc.run();
}

void listDevices() {
        int i, numDevices, defaultDisplayed;
        const PaDeviceInfo *deviceInfo;

        Pa_Initialize();

        numDevices = Pa_GetDeviceCount();

        printf( "Number of devices = %d\n", numDevices );
        int isInputDevice = 0;
        for( i=0; i<numDevices; i++ )
        {
                deviceInfo = Pa_GetDeviceInfo( i );
                int isInputDevice = (deviceInfo->maxInputChannels > 0);
                printf( "%sDeviceID: %d, Name: %s\n", (isInputDevice ? "Input" : "Output"), i, deviceInfo->name);
        }
        fprintf (stderr, "Press any key to close\n");
        getch();
}

int main (int argc, char **argv)
{
        int c;
        int inputDeviceId = -1;
        int outputDeviceId = -1;
        opterr = 0;
        const char* helpMessage =
                "-h : show this help message\n"
                "-i <int> : select the INPUT DEVICE by id\n"
                "-o <int> : select the OUPUT DEVICE by id\n"
                "-m <double> : SIGNAL MULTIPLIER\n"
                "-s <double> : SIGNAL MULTIPLIER STEP (press w or s while console focused to go up and down by this ammount.\n"
                "-d : list devices\n";

        while ((c = getopt (argc, argv, "i:o:l:m:s:hd")) != -1) {
                switch (c) {
                        case 'i':
                                inputDeviceId = atoi(optarg);
                                break;
                        case 'o':
                                outputDeviceId = atoi(optarg);
                                break;
                        case 'm':
                                multiplier = atof(optarg);
                                break;
                        case 's':
                                multiplierStep = atof(optarg);
                                break;
                        case 'd':
                                listDevices();
                                return 0;
                        case '?':
                                if (isprint (optopt))
                                        fprintf (stderr, "Unknown option `-%c'.\n", optopt);
                                else
                                        fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
                        case 'h':
                                fprintf (stderr, helpMessage);
                                fprintf (stderr, "Press any key to close\n");
                                getch();
                                return 1;
                        default:
                        abort ();
                }
        }

        // Start non blocking input thread
        std::thread nonBlockingInputThread(inputThread);


    PaStreamParameters inputParameters, outputParameters;
    PaStream *stream = NULL;
    PaError err;
    const PaDeviceInfo* inputInfo;
    const PaDeviceInfo* outputInfo;
    char *sampleBlock = NULL;
    int i;
    int numBytes;
    int numChannels;

    err = Pa_Initialize();
    if( err != paNoError ) error2(stream, err);

    inputParameters.device = (inputDeviceId == -1) ? Pa_GetDefaultInputDevice() : inputDeviceId; /* default input device */
    inputInfo = Pa_GetDeviceInfo( inputParameters.device );
    outputParameters.device = (outputDeviceId == -1) ? Pa_GetDefaultOutputDevice() : outputDeviceId; /* default output device */
    outputInfo = Pa_GetDeviceInfo( outputParameters.device );

        numChannels = inputInfo->maxInputChannels < outputInfo->maxOutputChannels
                ? inputInfo->maxInputChannels : outputInfo->maxOutputChannels;

    inputParameters.channelCount = numChannels;
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;
    inputParameters.suggestedLatency = inputInfo->defaultHighInputLatency ;
    inputParameters.hostApiSpecificStreamInfo = NULL;
    printf( "Input device # %d.\n", inputParameters.device );
    printf( "    Name: %s\n", inputInfo->name );


        outputParameters.channelCount = numChannels;
        outputParameters.sampleFormat = PA_SAMPLE_TYPE;
        outputParameters.suggestedLatency = outputInfo->defaultHighOutputLatency;
        outputParameters.hostApiSpecificStreamInfo = NULL;
    printf( "Output device # %d.\n", outputParameters.device );
    printf( "    Name: %s\n", outputInfo->name );

    /* -- setup -- */

    err = Pa_OpenStream(
              &stream,
              &inputParameters,
              &outputParameters,
              SAMPLE_RATE,
              FRAMES_PER_BUFFER,
              paClipOff,      /* we won't output out of range samples so don't bother clipping them */
              NULL, /* no callback, use blocking API */
              NULL ); /* no callback, so no callback userData */
    if( err != paNoError ) error2(stream, err);

    numBytes = FRAMES_PER_BUFFER * numChannels * SAMPLE_SIZE ;
    sampleBlock = (char *) malloc( numBytes );
    if( sampleBlock == NULL )
    {
        printf("Could not allocate record array.\n");
        error1(stream, sampleBlock);
    }

    err = Pa_StartStream( stream );
    if( err != paNoError ) error1(stream, sampleBlock);


        while (1) {
        // You may get underruns or overruns if the output is not primed by PortAudio.
        err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
        if( err ) xrun(stream, err, sampleBlock);

                int blockIndex;
                float* sampleBlockShort = (float*)sampleBlock;
                for (blockIndex = 0; blockIndex < FRAMES_PER_BUFFER; blockIndex++) {
                        /*
                        double dSample = (double)sampleBlockShort[blockIndex];
                        dSample *= multiplier;
                        if (dSample > 32767.0) dSample = 32767.0;
                        if (dSample < -32768.0) dSample = -32768.0;
                        sampleBlockShort[blockIndex] = (short)dSample;
                        */
                        sampleBlockShort[blockIndex] *= multiplier;
                }

                err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
                if( err ) xrun(stream, err, sampleBlock);
    }
    printf("Wire off.\n"); fflush(stdout);

    err = Pa_StopStream( stream );
    if( err != paNoError ) error1(stream, sampleBlock);

    free( sampleBlock );

    Pa_Terminate();
    return 0;

}

int xrun(PaStream *stream, int err, char* sampleBlock) {
    printf("err = %d\n", err); fflush(stdout);
    if( stream ) {
       Pa_AbortStream( stream );
       Pa_CloseStream( stream );
    }
    free( sampleBlock );
    Pa_Terminate();
    if( err & paInputOverflow )
       fprintf( stderr, "Input Overflow.\n" );
    if( err & paOutputUnderflow )
       fprintf( stderr, "Output Underflow.\n" );
    return -2;
}

void error1(PaStream *stream, char* sampleBlock) {
    free( sampleBlock );
    exit(-1);
}

void error2(PaStream *stream, int err) {
    if( stream ) {
       Pa_AbortStream( stream );
       Pa_CloseStream( stream );
    }
    Pa_Terminate();
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    exit(-1);
}

最佳答案

我发现您也可以为此使用 webrtc 库。它带有噪音抑制功能,非常方便。我不明白 compression_gain_db 和 target_level_dbfs 实际上做了什么,但是将它们设置为最高值似乎应用了最多的增益。按照@alexander 的建议使用 int16 解决了我的自定义解决方案的许多问题,并修复了遍历整个缓冲区的循环也有帮助。 webrtc 的解决方案和我自己的解决方案都可以通过以下示例代码实时运行。

下面包含代码示例。

$ ./main.exe -h
-h : show this help message
-i <int> : select the INPUT DEVICE by id
-o <int> : select the OUPUT DEVICE by id
-c <int [0,90]> : compression_gain_db
-t <int [0, 31]> : target_level_dbfs
-g <0 or 1> : toggle webrtc gain control on and off (1 by default)
-k <0 or 1> : toggle custom gain control on and off (1 by default)
-f <int [1, maxInt]> : customGainControlFactor
-q <int [0, 3]> : webrtc noise supression level, high is more suppression
-e <0 or 1> : toggle webrtc noise suppression on and off (1 by default)
-d : list devices

Real time controls:
compression_gain_db            UP_KEY='a' DOWN_KEY='s'
target_dbfs_level              UP_KEY='d' DOWN_KEY='f'
webrtcGainControlEnabled                           TOGGLE_KEY='g'
webrtcNoiseSuppressionLevel    UP_KEY='q' DOWN_KEY='w'
webrtcNoiseSuppressionEnabled                      TOGGLE_KEY='e'
customGainFactor               UP_KEY='h' DOWN_KEY='j'
customGainFactorEnabled                            TOGGLE_KEY='k'
Press any key to close

依赖项:tinycon、PortAudio、libwebrtc-audio-processing-devel

注意:我正在使用 cygwin,如果您在使用 libwebrtc 时遇到问题,请参阅 here

编译:g++ main.cpp tinycon.cpp -o main -L./-lcygportaudio-2 -lrt -lm -pthread -I/usr/include/webrtc_audio_processing/-DWEBRTC_WIN -DWEBRTC

主要.cpp

#include "portaudio.h"
#include <iostream>
#include <limits>
#include <chrono>
#include <thread>
#include <mutex>
#include "tinycon.h"

#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/include/trace.h"
using webrtc::AudioProcessing;
using webrtc::AudioFrame;
using webrtc::GainControl;
using webrtc::NoiseSuppression;

#define SAMPLE_RATE       (32000)
#define FRAMES_PER_BUFFER   (320)
#define DITHER_FLAG           (0)

#define PA_SAMPLE_TYPE paInt16
#define SAMPLE_SIZE (2)
#define SAMPLE_SILENCE  (0)
#define PRINTF_S_FORMAT "%d"

/*******************************************************************/
int customGainFactor = 1;
int customGainFactorStep = 1;
bool customGainControlEnabled = true;
int compression_gain_db = 1;
int compression_gain_dbStep = 1;
int target_level_dbfs = 1;
int target_level_dbfsStep = 1;
bool webrtcGainControlEnabled = true;
bool webrtcNoiseSuppressionEnabled = true;
int webrtcNoiseSuppressionLevel = 1;
int main(int argc, char **argv);
int xrun(PaStream *stream, int err, char* sampleBlock);
void error1(PaStream *stream, char* sampleBlock);
void error2(PaStream *stream, int err);
void listDevices();
webrtc::NoiseSuppression::Level webrtcNoiseSuppressionLevelToEnum(int level);
// Use tinycon and a second thread for non blocking input
class tcon : public tinyConsole
{
public:
        tcon (std::string s): tinyConsole(s) {;}

        int hotkeys(char c)
        {
                if (c == 'a') {
                        if (compression_gain_db >= (0+compression_gain_dbStep)) {
                                compression_gain_db -= compression_gain_dbStep;
                        }
                        printf( "Compression_gain_db: %d\n", compression_gain_db );
                        return 1;
                }
                if (c == 's') {
                        if (compression_gain_db <= (90-compression_gain_dbStep)) {
                                compression_gain_db += compression_gain_dbStep;
                        }
                        printf( "Compression_gain_db: %d\n", compression_gain_db );
                        return 1;
                }
                if (c == 'd') {
                        if (target_level_dbfs >= (0+target_level_dbfsStep)) {
                                target_level_dbfs -= target_level_dbfsStep;
                        }
                        printf( "target_level_dbfs: %d\n", target_level_dbfs );
                        return 1;
                }
                if (c == 'f') {
                        if (target_level_dbfs <= (31-target_level_dbfsStep)) {
                                target_level_dbfs += target_level_dbfsStep;
                        }
                        printf( "target_level_dbfs: %d\n", target_level_dbfs );
                        return 1;
                }
                if (c == 'g') {
                        webrtcGainControlEnabled = !webrtcGainControlEnabled;
                        printf("webrtcGainControlEnabled: %s\n", (webrtcGainControlEnabled) ? "true" : "false");
                        return 1;
                }
                if (c == 'h') {
                        if (customGainFactor >= (1+customGainFactorStep)) {
                                customGainFactor -= customGainFactorStep;
                        }
                        printf( "customGainFactor: %d\n", customGainFactor );
                        return 1;
                }
                if (c == 'j') {
                        customGainFactor += customGainFactorStep;
                        printf( "customGainFactor: %d\n", customGainFactor );
                        return 1;
                }
                if (c == 'k') {
                        customGainControlEnabled = !customGainControlEnabled;
                        printf("customGainControlEnabled: %s\n", (customGainControlEnabled) ? "true" : "false");
                        return 1;
                }
                if (c == 'q') {
                        if (webrtcNoiseSuppressionLevel <= (3-1)) {
                                webrtcNoiseSuppressionLevel += 1;
                        }
                        printf( "webrtcNoiseSuppressionLevel: %d\n", webrtcNoiseSuppressionLevel );
                        return 1;
                }
                if (c == 'w') {
                        if (webrtcNoiseSuppressionLevel >= (0+1)) {
                                webrtcNoiseSuppressionLevel -= 1;
                        }
                        printf( "webrtcNoiseSuppressionLevel: %d\n", webrtcNoiseSuppressionLevel );
                        return 1;
                }
                if (c == 'e') {
                        webrtcNoiseSuppressionEnabled = !webrtcNoiseSuppressionEnabled;
                        printf("webrtcNoiseSuppressionEnabled: %s\n", (webrtcNoiseSuppressionEnabled) ? "true" : "false");
                        return 1;
                }
                return 0;
        }
};
int inputThread() {
        tcon tc (std::string(""));
        tc.run();
}

void listDevices() {
        int i, numDevices, defaultDisplayed;
        const PaDeviceInfo *deviceInfo;

        Pa_Initialize();

        numDevices = Pa_GetDeviceCount();

        printf( "Number of devices = %d\n", numDevices );
        int isInputDevice = 0;
        for( i=0; i<numDevices; i++ )
        {
                deviceInfo = Pa_GetDeviceInfo( i );
                int isInputDevice = (deviceInfo->maxInputChannels > 0);
                printf( "%sDeviceID: %d, Name: %s\n", (isInputDevice ? "Input" : "Output"), i, deviceInfo->name);
        }
        fprintf (stderr, "Press any key to close\n");
        getch();
}

int main (int argc, char **argv)
{
        int c;
        int inputDeviceId = -1;
        int outputDeviceId = -1;
        opterr = 0;
        const char* helpMessage =
                "-h : show this help message\n"
                "-i <int> : select the INPUT DEVICE by id\n"
                "-o <int> : select the OUPUT DEVICE by id\n"
                "-c <int [0,90]> : compression_gain_db\n"
                "-t <int [0, 31]> : target_level_dbfs\n"
                "-g <0 or 1> : toggle webrtc gain control on and off (1 by default)\n"
                "-k <0 or 1> : toggle custom gain control on and off (1 by default)\n"
                "-f <int [1, maxInt]> : customGainControlFactor\n"
                "-q <int [0, 5]> : webrtc noise supression level, high is more suppression\n"
                "-e <0 or 1> : toggle webrtc noise suppression on and off (1 by default)\n"
                "-d : list devices\n"
                "\n"
                "Real time controls:\n"
                "compression_gain_db            UP_KEY='a' DOWN_KEY='s'\n"
                "target_dbfs_level              UP_KEY='d' DOWN_KEY='f'\n"
                "webrtcGainControlEnabled                           TOGGLE_KEY='g'\n"
                "webrtcNoiseSuppressionLevel    UP_KEY='q' DOWN_KEY='w'\n"
                "webrtcNoiseSuppressionEnabled                      TOGGLE_KEY='e'\n"
                "customGainFactor               UP_KEY='h' DOWN_KEY='j'\n"
                "customGainFactorEnabled                            TOGGLE_KEY='k'\n";

        while ((c = getopt (argc, argv, "i:o:c:t:g:k:f:w:q:hd")) != -1) {
                switch (c) {
                        case 'i':
                                inputDeviceId = atoi(optarg);
                                break;
                        case 'o':
                                outputDeviceId = atoi(optarg);
                                break;
                        case 'c':
                                compression_gain_db = atoi(optarg);
                                break;
                        case 't':
                                target_level_dbfs = atoi(optarg);
                                break;
                        case 'g':
                                webrtcGainControlEnabled = (atoi(optarg) == 1) ? true : false;
                                break;
                        case 'f':
                                customGainFactor = atoi(optarg);
                                break;
                        case 'k':
                                customGainControlEnabled = (atoi(optarg) == 1) ? true : false;
                                break;
                        case 'w':
                                webrtcNoiseSuppressionLevel = atoi(optarg);
                                break;
                        case 'e':
                                webrtcNoiseSuppressionEnabled = (atoi(optarg) == 1) ? true : false;
                                break;
                        case 'd':
                                listDevices();
                                return 0;
                        case '?':
                                if (isprint (optopt))
                                        fprintf (stderr, "Unknown option `-%c'.\n", optopt);
                                else
                                        fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
                        case 'h':
                                fprintf (stderr, helpMessage);
                                fprintf (stderr, "Press any key to close\n");
                                getch();
                                return 1;
                        default:
                        abort ();
                }
        }

        // Start non blocking input thread
        std::thread nonBlockingInputThread(inputThread);


    PaStreamParameters inputParameters, outputParameters;
    PaStream *stream = NULL;
    PaError err;
    const PaDeviceInfo* inputInfo;
    const PaDeviceInfo* outputInfo;
    char *sampleBlock = NULL;
    int i;
    int numBytes;
    int numChannels;

    err = Pa_Initialize();
    if( err != paNoError ) error2(stream, err);

    inputParameters.device = (inputDeviceId == -1) ? Pa_GetDefaultInputDevice() : inputDeviceId; /* default input device */
    inputInfo = Pa_GetDeviceInfo( inputParameters.device );
    outputParameters.device = (outputDeviceId == -1) ? Pa_GetDefaultOutputDevice() : outputDeviceId; /* default output device */
    outputInfo = Pa_GetDeviceInfo( outputParameters.device );

        numChannels = inputInfo->maxInputChannels < outputInfo->maxOutputChannels
                ? inputInfo->maxInputChannels : outputInfo->maxOutputChannels;

    inputParameters.channelCount = numChannels;
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;
    inputParameters.suggestedLatency = inputInfo->defaultHighInputLatency ;
    inputParameters.hostApiSpecificStreamInfo = NULL;
    printf( "Input device # %d.\n", inputParameters.device );
    printf( "    Name: %s\n", inputInfo->name );


        outputParameters.channelCount = numChannels;
        outputParameters.sampleFormat = PA_SAMPLE_TYPE;
        outputParameters.suggestedLatency = outputInfo->defaultHighOutputLatency;
        outputParameters.hostApiSpecificStreamInfo = NULL;
    printf( "Output device # %d.\n", outputParameters.device );
    printf( "    Name: %s\n", outputInfo->name );

    /* -- setup -- */

    err = Pa_OpenStream(
              &stream,
              &inputParameters,
              &outputParameters,
              SAMPLE_RATE,
              FRAMES_PER_BUFFER,
              paClipOff,      /* we won't output out of range samples so don't bother clipping them */
              NULL, /* no callback, use blocking API */
              NULL ); /* no callback, so no callback userData */
    if( err != paNoError ) error2(stream, err);

    numBytes = FRAMES_PER_BUFFER * numChannels * SAMPLE_SIZE ;
    sampleBlock = (char *) malloc( numBytes );
    if( sampleBlock == NULL )
    {
        printf("Could not allocate record array.\n");
        error1(stream, sampleBlock);
    }

        // Configure webrtc::audioprocessing
        int webrtcErr;
        AudioProcessing* apm = AudioProcessing::Create();

        apm->high_pass_filter()->Enable(true);

        apm->noise_suppression()->set_level(webrtcNoiseSuppressionLevelToEnum(webrtcNoiseSuppressionLevel));
        apm->noise_suppression()->Enable(webrtcNoiseSuppressionEnabled);

        apm->gain_control()->set_mode(apm->gain_control()->kFixedDigital);
        apm->gain_control()->set_compression_gain_db(compression_gain_db);
        apm->gain_control()->set_target_level_dbfs(target_level_dbfs);
        apm->gain_control()->Enable(webrtcGainControlEnabled);

    err = Pa_StartStream( stream );
    if( err != paNoError ) error1(stream, sampleBlock);

        while (1) {
        // You may get underruns or overruns if the output is not primed by PortAudio.
        err = Pa_ReadStream( stream, sampleBlock, FRAMES_PER_BUFFER );
        if( err ) xrun(stream, err, sampleBlock);

                // Run custom gain solution
                if (customGainControlEnabled) {
                        int blockIndex;
                        short* sampleBlockShort = (short*)sampleBlock;
                        for (blockIndex = 0; blockIndex < FRAMES_PER_BUFFER*numChannels; blockIndex++) {
                                        int iSample = (int)sampleBlockShort[blockIndex];
                                        iSample *= customGainFactor;
                                        if (iSample > std::numeric_limits<short>::max())
                                        iSample =
                                                  (iSample > std::numeric_limits<short>::max()) ? std::numeric_limits<short>::max()
                                                : (iSample < std::numeric_limits<short>::min()) ? std::numeric_limits<short>::min()
                                                : iSample;
                                        sampleBlockShort[blockIndex] = (short)iSample;
                        }
                }

                // Apply webrtc gain and noise suppression
                apm->noise_suppression()->set_level(webrtcNoiseSuppressionLevelToEnum(webrtcNoiseSuppressionLevel));
                apm->noise_suppression()->Enable(webrtcNoiseSuppressionEnabled);
                apm->gain_control()->set_compression_gain_db(compression_gain_db);
                apm->gain_control()->set_target_level_dbfs(target_level_dbfs);
                apm->gain_control()->Enable(webrtcGainControlEnabled);

                webrtc::AudioFrame frame;
                frame.num_channels_ = numChannels;
                frame.sample_rate_hz_ = SAMPLE_RATE;
                frame.samples_per_channel_ = FRAMES_PER_BUFFER;

                memcpy(frame.data_, sampleBlock, numBytes);
                if ((webrtcErr = apm->ProcessStream(&frame)) < 0) {
                        printf("Error Code: %d\n", webrtcErr); fflush(stdout);
                        return -1;
                }
                memcpy(sampleBlock, frame.data_, numBytes);

                err = Pa_WriteStream( stream, sampleBlock, FRAMES_PER_BUFFER );
                if( err ) xrun(stream, err, sampleBlock);
    }
    printf("Wire off.\n"); fflush(stdout);

    err = Pa_StopStream( stream );
    if( err != paNoError ) error1(stream, sampleBlock);

    free( sampleBlock );

    Pa_Terminate();
    return 0;

}

int xrun(PaStream *stream, int err, char* sampleBlock) {
    printf("err = %d\n", err); fflush(stdout);
    if( stream ) {
       Pa_AbortStream( stream );
       Pa_CloseStream( stream );
    }
    free( sampleBlock );
    Pa_Terminate();
    if( err & paInputOverflow )
       fprintf( stderr, "Input Overflow.\n" );
    if( err & paOutputUnderflow )
       fprintf( stderr, "Output Underflow.\n" );
    return -2;
}

void error1(PaStream *stream, char* sampleBlock) {
    free( sampleBlock );
    exit(-1);
}

void error2(PaStream *stream, int err) {
    if( stream ) {
       Pa_AbortStream( stream );
       Pa_CloseStream( stream );
    }
    Pa_Terminate();
    fprintf( stderr, "An error occured while using the portaudio stream\n" );
    fprintf( stderr, "Error number: %d\n", err );
    fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    exit(-1);
}

webrtc::NoiseSuppression::Level webrtcNoiseSuppressionLevelToEnum(int level) {
        switch (level) {
                case 0 : return webrtc::NoiseSuppression::Level::kLow;
                case 1 : return webrtc::NoiseSuppression::Level::kModerate;
                case 2 : return webrtc::NoiseSuppression::Level::kHigh;
                case 3 : return webrtc::NoiseSuppression::Level::kVeryHigh;
        }
}

关于c++ - 以编程方式增加麦克风增益,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42748949/

有关c++ - 以编程方式增加麦克风增益的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  5. ruby-on-rails - 正确的 Rails 2.1 做事方式 - 2

    question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  8. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  9. 网络编程套接字 - 2

    网络编程套接字网络编程基础知识理解源`IP`地址和目的`IP`地址理解源MAC地址和目的MAC地址认识端口号理解端口号和进程ID理解源端口号和目的端口号认识`TCP`协议认识`UDP`协议网络字节序socket编程接口`sockaddr``UDP`网络程序服务器端代码逻辑:需要用到的接口服务器端代码`udp`客户端代码逻辑`udp`客户端代码`TCP`网络程序服务器代码逻辑多个版本服务器单进程版本多进程版本多线程版本线程池版本服务器端代码客户端代码逻辑客户端代码TCP协议通讯流程TCP协议的客户端/服务器程序流程三次握手(建立连接)数据传输四次挥手(断开连接)TCP和UDP对比网络编程基础知识

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐