如何使用Linux中的套接字层在C ++上编写.wav文件?

时间:2014-05-09 18:08:15

标签: c++ linux audio tcp wav

我试图通过套接字在Linux上通过TCP发送C ++中的wav文件,但我不明白如何正确读取wav文件。

我的目标是将客户端上的文件读入char数组,并使用" write()"到服务器,服务器应该再次将数据写入本地wav文件。

我读了这样的.wav文件:

////////////define socket - left out for simplicity

ifstream file ("audio.wav", ios::in|ios::binary|ios::ate); //open .wav file
char * buffer; //declare data buffer, should contain .wav data to write to socket
streampos filesize; //size of file
int n; //number of written bytes

//if file opened correctly, read content and write to socket
if (file.is_open()){
    filesize = file.tellg();
    buffer = new char [filesize];
    file.seekg (0, ios::beg);
    file.read (buffer, filesize);
    file.close();
    n = write(socket, buffer, sizeof(buffer));
 }

在服务器上,这将返回数组" RIFF"长度" 4",所以它是wav文件头部的一部分。

如何正确读取整个.wav文件内容以写入TCP套接字?

感谢。

4 个答案:

答案 0 :(得分:2)

buffer的类型为char*,因此sizeof(buffer)是平台上普通数据指针的大小。所以你要在你的套接字上写4或8个字节(假设普通的平台形式)。

您需要将filesize放入write来电,而不是sizeof(buffer)

sizeof是一个编译时构造。它是在编译代码时进行评估的。它不能返回在运行时确定的大小。)

答案 1 :(得分:2)

在行n = write(socket, buffer, sizeof(buffer));中,最后一个缓冲区的值变为平台上指针的大小。由于只发送了四个字节,我将假设您使用的是32位平台或以32位模式编译应用程序。

替换sizeof(buffer)只是部分解决方案,因为write()可能无法一次写入所有数据。您需要检查从write()返回的值,并记录已写入套接字的字节数。

答案 2 :(得分:2)

这很简单:filesize是文件的大小(以字节为单位)。但是,sizeof(buffer)在32位操作系统上只有4。像这样修改你的代码:

if(file.is_open()) {
    filesize = file.tellg();
    buffer = new char [filesize];
    file.seekg (0, ios::beg);
    file.read (buffer, filesize);
    file.close();
    n = write_all(socket, buffer, filesize); // use filesize here
    delete[] buffer; // !!
}

为了简化另一方的处理,您可能需要先发送filesize以避免解析RIFF标头以了解要接受的字节数。我还建议分配一个较小的缓冲区并多次读取以发送较大的文件:

if(file.is_open()) {
    filesize = file.tellg();
    file.seekg(0, ios::beg);

    uint32_t remains = filesize;
    write(socket, &remains, sizeof(uint32_t));
    // write 4B with size of the file (optional)

    buffer = new char[(filesize > 4096)? 4096 : filesize];
    // only up to 4k buffer to avoid running out of memory

    n = 0;
    while(remains > 0) {
        int chunk = (remains > 4096)? 4096 : remains;
        // decide how much to read in at one time (not more than size of the buffer)

        file.read(buffer, chunk);
        n += write_all(socket, buffer, chunk);
        // read a chunk and write it to the socket

        remains -= chunk;
        // update number of bytes that remains to be transferred
    }
    // send the file several times

    file.close();
    delete[] buffer; // !!
}

您可能会注意到使用辅助函数write_all。这是必需的,因为套接字可能已满,然后write将不会写入提供给它的所有数据。它看起来像这样:

size_t write_all(int socket, const char *buffer, size_t size)
{
    size_t n = 0;
    while(size > 0) {
        size_t written = write(socket, buffer, size);
        if(written == -1)
            return written; // handle errors
        n += written;
        size -= written;
    }
    return n;
}

答案 3 :(得分:1)

我使用sndfile来处理wav文件。