对 FILE 的操作到对 QByteArray 的操作?
Operation on FILE to operation on QByteArray?
我有以下代码将原始音频文件转换为 wav 文件:
int MainWindow::rawToWav(const char *rawfn, const char *wavfn, long samplingRate)
{
long chunksize=0x10;
int statusCollect = 0;
struct
{
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} fmt;
errno_t err;
FILE *raw;
err = fopen_s(&raw, rawfn, "rb");
if(!raw)
return -2;
fseek(raw, 0, SEEK_END);
long bytes = ftell(raw);
fseek(raw, 0, SEEK_SET);
long samplecount = bytes/2;
long riffsize = samplecount*2+0x24;
long datasize = samplecount*2;
FILE *wav;
err = fopen_s(&wav, wavfn, "wb");
if(!wav)
{
fclose(raw);
return -3;
}
fwrite( "RIFF", 1, 4, wav );
fwrite( &riffsize, 4, 1, wav );
fwrite( "WAVEfmt ", 1, 8, wav );
fwrite( &chunksize, 4, 1, wav );
int bitsPerSample = 16;
int bytesPerSample = bitsPerSample/8;
int channel = 2;
fmt.wFormatTag = 1; // PCM
fmt.wChannels = channel; // MONO
fmt.dwSamplesPerSec = samplingRate;
fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
fmt.wBlockAlign = channel*bytesPerSample;
fmt.wBitsPerSample = bitsPerSample;
fwrite( &fmt, sizeof(fmt), 1, wav );
fwrite( "data", 1, 4, wav );
fwrite( &datasize, 4, 1, wav );
short buff[1024];
while( !feof(raw) )
{
int cnt=fread(buff,2,1024,raw);
if( cnt == 0 )
break;
fwrite(buff,2,cnt,wav);
}
statusCollect = fclose( raw );
statusCollect += fclose( wav );
return statusCollect;
}
我想对 QByteArray 类型而不是 FILE 类型数据进行完全相同的操作。
所以我正在尝试以下方式。首先,我尝试在 QByteArray object 上添加 wav header。然后我在程序上上传原始音频文件。然后我将该原始数据添加到我已经添加了 wav header 的 QByteArray object。然后我将 QByteArray 保存为 wav 文件。
void MainWindow::rawToWavQT(QByteArray* arr, long samplingRate, long sizeOfRawFile)
{
long chunksize=0x10;
struct
{
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} fmt;
long samplecount = sizeOfRawFile/2;
long riffsize = samplecount*2+0x24;
long datasize = samplecount*2;
arr->append("RIFF");// fwrite( "RIFF", 1, 4, wav );
arr->append((const char*)&riffsize);// fwrite( &riffsize, 4, 1, wav );
arr->append("WAVEfmt ");// fwrite( "WAVEfmt ", 1, 8, wav );
arr->append((const char*)&chunksize);// fwrite( &chunksize, 4, 1, wav );
int bitsPerSample = 16;
int bytesPerSample = bitsPerSample/8;
int channel = 2;
fmt.wFormatTag = 1; // PCM
fmt.wChannels = channel; // MONO
fmt.dwSamplesPerSec = samplingRate;
fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
fmt.wBlockAlign = channel*bytesPerSample;
fmt.wBitsPerSample = bitsPerSample;
arr->append((const char*)&fmt);// fwrite( &fmt, sizeof(fmt), 1, wav );
arr->append("data");// fwrite( "data", 1, 4, wav );
arr->append((const char*)&datasize);// fwrite( &datasize, 4, 1, wav );
}
但是这种将 header 添加到 QByteArray 然后添加原始数据的方法无法生成正确类型的 wav 文件,因为它无法播放。从第二个函数判断我做错了什么,我在第二个函数中执行与第一个函数相同的操作,但在 QByteArray object 而不是 FILE object?
谢谢。
您的数据串联功能仅在第一个空字节处停止,丢失重要数据并破坏对齐。相反,您还想指定要附加的 length,方式与 fwrite
类似。
解决方案:将您的 append()
语句从单个 const char *
参数替换为使用您的数据和数据长度构造的 QByteArray
。
改变
arr->append((const char*)&riffsize);
到
arr->append(QByteArray((const char*)&riffsize, 4));
其他原始数据 append
语句也类似。
我有以下代码将原始音频文件转换为 wav 文件:
int MainWindow::rawToWav(const char *rawfn, const char *wavfn, long samplingRate)
{
long chunksize=0x10;
int statusCollect = 0;
struct
{
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} fmt;
errno_t err;
FILE *raw;
err = fopen_s(&raw, rawfn, "rb");
if(!raw)
return -2;
fseek(raw, 0, SEEK_END);
long bytes = ftell(raw);
fseek(raw, 0, SEEK_SET);
long samplecount = bytes/2;
long riffsize = samplecount*2+0x24;
long datasize = samplecount*2;
FILE *wav;
err = fopen_s(&wav, wavfn, "wb");
if(!wav)
{
fclose(raw);
return -3;
}
fwrite( "RIFF", 1, 4, wav );
fwrite( &riffsize, 4, 1, wav );
fwrite( "WAVEfmt ", 1, 8, wav );
fwrite( &chunksize, 4, 1, wav );
int bitsPerSample = 16;
int bytesPerSample = bitsPerSample/8;
int channel = 2;
fmt.wFormatTag = 1; // PCM
fmt.wChannels = channel; // MONO
fmt.dwSamplesPerSec = samplingRate;
fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
fmt.wBlockAlign = channel*bytesPerSample;
fmt.wBitsPerSample = bitsPerSample;
fwrite( &fmt, sizeof(fmt), 1, wav );
fwrite( "data", 1, 4, wav );
fwrite( &datasize, 4, 1, wav );
short buff[1024];
while( !feof(raw) )
{
int cnt=fread(buff,2,1024,raw);
if( cnt == 0 )
break;
fwrite(buff,2,cnt,wav);
}
statusCollect = fclose( raw );
statusCollect += fclose( wav );
return statusCollect;
}
我想对 QByteArray 类型而不是 FILE 类型数据进行完全相同的操作。
所以我正在尝试以下方式。首先,我尝试在 QByteArray object 上添加 wav header。然后我在程序上上传原始音频文件。然后我将该原始数据添加到我已经添加了 wav header 的 QByteArray object。然后我将 QByteArray 保存为 wav 文件。
void MainWindow::rawToWavQT(QByteArray* arr, long samplingRate, long sizeOfRawFile)
{
long chunksize=0x10;
struct
{
unsigned short wFormatTag;
unsigned short wChannels;
unsigned long dwSamplesPerSec;
unsigned long dwAvgBytesPerSec;
unsigned short wBlockAlign;
unsigned short wBitsPerSample;
} fmt;
long samplecount = sizeOfRawFile/2;
long riffsize = samplecount*2+0x24;
long datasize = samplecount*2;
arr->append("RIFF");// fwrite( "RIFF", 1, 4, wav );
arr->append((const char*)&riffsize);// fwrite( &riffsize, 4, 1, wav );
arr->append("WAVEfmt ");// fwrite( "WAVEfmt ", 1, 8, wav );
arr->append((const char*)&chunksize);// fwrite( &chunksize, 4, 1, wav );
int bitsPerSample = 16;
int bytesPerSample = bitsPerSample/8;
int channel = 2;
fmt.wFormatTag = 1; // PCM
fmt.wChannels = channel; // MONO
fmt.dwSamplesPerSec = samplingRate;
fmt.dwAvgBytesPerSec = samplingRate*channel*bytesPerSample; // 16 bit
fmt.wBlockAlign = channel*bytesPerSample;
fmt.wBitsPerSample = bitsPerSample;
arr->append((const char*)&fmt);// fwrite( &fmt, sizeof(fmt), 1, wav );
arr->append("data");// fwrite( "data", 1, 4, wav );
arr->append((const char*)&datasize);// fwrite( &datasize, 4, 1, wav );
}
但是这种将 header 添加到 QByteArray 然后添加原始数据的方法无法生成正确类型的 wav 文件,因为它无法播放。从第二个函数判断我做错了什么,我在第二个函数中执行与第一个函数相同的操作,但在 QByteArray object 而不是 FILE object?
谢谢。
您的数据串联功能仅在第一个空字节处停止,丢失重要数据并破坏对齐。相反,您还想指定要附加的 length,方式与 fwrite
类似。
解决方案:将您的 append()
语句从单个 const char *
参数替换为使用您的数据和数据长度构造的 QByteArray
。
改变
arr->append((const char*)&riffsize);
到
arr->append(QByteArray((const char*)&riffsize, 4));
其他原始数据 append
语句也类似。