在C中通过套接字发送音频

时间:2017-12-14 18:28:15

标签: c sockets audio network-programming portaudio

我正在尝试将音频发送到我通过套接字构建的服务器。我正在为客户端使用C.基本上我的代码记录了最多10秒的音频,然后我想通过套接字将它发送到我的服务器。如何发送通过C中的套接字录制的音频?我不想将音频保存为文件...我想将其直接发送到服务器。

这是我的代码:

// Standard libraries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

// Audio libraries
#include "portaudio.h"

// Audio parameters
#define RECORD_AUDIO_THRESHOLD 0.003
#define SILENCE_SECONDS 1
#define MAX_RECORDING_SECONDS 10
#define AUDIO_FORMAT paFloat32
typedef float SAMPLE_TYPE;
#define NUM_INPUT_CHANNELS 1
#define NUM_OUTPUT_CHANNELS 1
#define SAMPLE_RATE 44100
#define FRAMES_PER_BUFFER 512

// Server details
#define SERVER_ADDRESS "127.0.0.1"
#define SERVER_PORT 8080

// Global variables
int sock = 0;

// ######################## Structures ########################

typedef struct
{
    int             recording;
    int             maxFrameIndex;
    int             currentFrameIndex;
    int             silenceStartFrameIndex;
    double          averageAmplitude;
    SAMPLE_TYPE     *recordedSamples;
}
paAudioData;

// ######################## Helper Functions ########################

void setup(void)
{

}

// ######################## Helper Functions ########################



// ######################## Callbacks ########################

static int paListeningCallback( const void *inputBuffer,
                                void *outputBuffer,
                                unsigned long framesPerBuffer,
                                const PaStreamCallbackTimeInfo* timeInfo,
                                PaStreamCallbackFlags statusFlags,
                                void *userData  )
{
    paAudioData *data = (paAudioData*)userData;
    const SAMPLE_TYPE *rptr = (const SAMPLE_TYPE*)inputBuffer;
    SAMPLE_TYPE *wptr = &data->recordedSamples[data->currentFrameIndex * NUM_INPUT_CHANNELS];
    unsigned long framesLeft = data->maxFrameIndex - data->currentFrameIndex;
    SAMPLE_TYPE amplitude, frameData;
    long framesToCalc, i;
    int j;

    // Prevent unused variable warnings.
    (void) outputBuffer;
    (void) timeInfo;
    (void) statusFlags;
    (void) userData;

    if (framesLeft < framesPerBuffer && data->recording)
        framesToCalc = framesLeft;
    else
        framesToCalc = framesPerBuffer;

    for (i = 0; i < framesToCalc; i++)
    {
        frameData = *rptr++;
        amplitude = frameData;
        if (amplitude < 0) amplitude = -amplitude; // ABS
        if ((amplitude - data->averageAmplitude) >= RECORD_AUDIO_THRESHOLD)
        {
            if (!(data->recording))
            {
                data->recording = 1;
                data->currentFrameIndex = 0;
                printf("Recording...\n");
            }
            data->silenceStartFrameIndex = 0;
            for (j = 0; j < NUM_INPUT_CHANNELS; j++) *wptr++ = frameData;
        }
        else if (data->recording)
        {
            if (data->silenceStartFrameIndex == 0) data->silenceStartFrameIndex = data->currentFrameIndex + i;

            if ((data->currentFrameIndex + i) == data->silenceStartFrameIndex + (SILENCE_SECONDS * SAMPLE_RATE * NUM_INPUT_CHANNELS))
            {
                data->recording = 0;
                data->currentFrameIndex += i;
                printf("Stopped recording.\n");

                // TODO: Send audio to server via socket

                return 0;
            }
            for (j = 0; j < NUM_INPUT_CHANNELS; j++) *wptr++ = frameData;
        }
    }
    data->currentFrameIndex += framesToCalc;
    return 0;
}

// ######################## Main ########################

int main(void)
{
    PaStream*           stream;
    PaError             err;
    paAudioData         data;
    int                 i,
                        totalFrames,
                        numSamples,
                        numBytes;
    struct sockaddr_in  address;
    int                 valread;
    struct sockaddr_in  serv_addr;
    char                buffer[2048] = {0};

    setup();

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("\n Socket creation error \n");
        return -1;
    }

    memset(&serv_addr, '0', sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(SERVER_PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form
    if(inet_pton(AF_INET, SERVER_ADDRESS, &serv_addr.sin_addr) <= 0)
    {
        printf("\nInvalid address/ Address not supported \n");
        return -1;
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
    {
        printf("\nConnection Failed \n");
        return -1;
    }

    // Initialize audio data
    data.maxFrameIndex = totalFrames = MAX_RECORDING_SECONDS * SAMPLE_RATE;
    data.currentFrameIndex = 0;
    numSamples = totalFrames * NUM_INPUT_CHANNELS;
    numBytes = numSamples * sizeof(SAMPLE_TYPE);
    data.recordedSamples = (SAMPLE_TYPE *) malloc(numBytes);
    data.averageAmplitude = 0;
    data.recording = 0;

    // Initialize PortAudio
    err = Pa_Initialize();
    if (err != paNoError) goto paError;

    // Open an audio listening stream
    err = Pa_OpenDefaultStream( &stream,
                                NUM_INPUT_CHANNELS,
                                0,
                                AUDIO_FORMAT,
                                SAMPLE_RATE,
                                FRAMES_PER_BUFFER,
                                paListeningCallback,
                                &data  );
    if (err != paNoError) goto paError;

    // Start passive audio listening
    err = Pa_StartStream(stream);
    if (err != paNoError) goto paError;

    Pa_Sleep(10000);

    // Terminate PortAudio
    err = Pa_Terminate();
    if (err != paNoError) goto paError;

    // Print PortAudio error and exit
    paError:
        printf("PortAudio error: %s\n", Pa_GetErrorText(err));
        return 0;

    return 0;
}

0 个答案:

没有答案