Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 操作NSMutableData中的字节时出现问题-波头信息_Iphone - Fatal编程技术网

Iphone 操作NSMutableData中的字节时出现问题-波头信息

Iphone 操作NSMutableData中的字节时出现问题-波头信息,iphone,Iphone,我试图操纵一个wave文件头。我已将该文件加载到NSMutableData中,并尝试更改wav文件头信息。我的问题是在线: [maindata replaceBytesInRange:range withBytes:((UInt32 *)tfSC1Length)]; 我收到一个EXC\u BAD\u访问错误。我不明白为什么。有什么想法吗 我使用的代码如下: // calculate total file length (minus 8 for the header), chunk size,

我试图操纵一个wave文件头。我已将该文件加载到NSMutableData中,并尝试更改wav文件头信息。我的问题是在线:

[maindata replaceBytesInRange:range withBytes:((UInt32 *)tfSC1Length)];
我收到一个EXC\u BAD\u访问错误。我不明白为什么。有什么想法吗

我使用的代码如下:

// calculate total file length (minus 8 for the header), chunk size, number of channels, sample rate and bits per sample
int tfLength        = ([maindata length] - 8);
int tfChannels      = 1;   // mono
int tfSampleRate    = 44100;
int tfDataLength    = ([maindata length] - 44);
int tfBitsPerSample = 16;

int tfSC1Length     = 16;
int tfAudioFormat   = 1;

//we are rebuilding the header for the wave files...

// chunk identifier
((char *)[maindata mutableBytes])[0] = 'R';
((char *)[maindata mutableBytes])[1] = 'I';
((char *)[maindata mutableBytes])[2] = 'F';
((char *)[maindata mutableBytes])[3] = 'F';

// size (less 8 bytes)
NSRange range;
range.location = 4;
range.length = 4;
[maindata replaceBytesInRange:range withBytes:(UInt32 *)tfLength];

// the file format
((char *)[maindata mutableBytes])[8]  = 'W';
((char *)[maindata mutableBytes])[9]  = 'A';
((char *)[maindata mutableBytes])[10] = 'V';
((char *)[maindata mutableBytes])[11] = 'E';

// subchunk1 ID
((char *)[maindata mutableBytes])[12] = 'f';
((char *)[maindata mutableBytes])[13] = 'm';
((char *)[maindata mutableBytes])[14] = 't';
((char *)[maindata mutableBytes])[15] = ' ';

// subchunk length
range.location = 16;
range.length   = 4;
[maindata replaceBytesInRange:range withBytes:((UInt32 *)tfSC1Length)];

// audio format
range.location = 20;
range.length   = 2;
[maindata replaceBytesInRange:range withBytes:((UInt16 *)tfAudioFormat)];

// number of channels
range.location = 22;
range.length   = 2;
[maindata replaceBytesInRange:range withBytes:((UInt16 *)tfChannels)];

// sample rate
range.location = 24;
range.length   = 4;
[maindata replaceBytesInRange:range withBytes:((UInt32 *)tfSampleRate)];

// byte rate
range.location = 28;
range.length   = 4;
[maindata replaceBytesInRange:range withBytes:((UInt32 *)(tfSampleRate * ((tfBitsPerSample * tfChannels) / 8)))];

// block align
range.location = 32;
range.length   = 2;
[maindata replaceBytesInRange:range withBytes:((UInt16 *)((tfBitsPerSample * tfChannels) / 8))];

// bits per sample
range.location = 34;
range.length   = 2; 
[maindata replaceBytesInRange:range withBytes:((UInt16 *)tfBitsPerSample)];

// adjust the length field of the wave file...
((char *)[maindata mutableBytes])[36] = 'd';
((char *)[maindata mutableBytes])[37] = 'a';
((char *)[maindata mutableBytes])[38] = 't';
((char *)[maindata mutableBytes])[39] = 'a';

// length of the audio data
range.location = 40;
range.length   = 4;
[maindata replaceBytesInRange:range withBytes:(UInt32 *)tfDataLength];
如果要将整数值复制到数据缓冲区,则需要使用“&”运算符获取整数值的地址:

因此,不是:

[maindata replaceBytesInRange:range withBytes:(UInt32 *)tfLength];
使用:

这导致了你的崩溃,因为它现在把你的长度当成了指针

另外,对于16位和32位整数,wav文件格式所期望的字节顺序是什么?它与iPhone和iPhone模拟器上的字节顺序相同吗?可以使用转换为正确的字节顺序


另外,在声明长度时,我会使用计数的确切类型(UInt32、UInt16)而不是int,以确保正确复制长度。现在的实现方式是假设UInt32是二进制的,与int相同(可能为true),int的前2个字节与UInt16相同,具有相同的值(不一定为true)。

我建议使用结构引用头:

typedef struct {
    UInt32      riffChunkID;        // Always RIFF, in big endian. Integer fields are little-ending.
    UInt32      fileLength;
    UInt32      waveFileID;     // 'WAVE' for Wave files.
    UInt32      formatChunkID;  // 'fmt '
    UInt32      formatChunkSize;
    SInt16      formatTag;          // Wave Format ID: see constants
    SInt16      channels;           // Number of Channels: 1=mono, 2=stereo
    SInt32      sampleRate;         // Sample Rate: samples per second
    SInt32      bytesPerSec;        // sampleRate * blockAlign
    SInt16      blockAlign;         // sample frame size = channels * sampleSize / 8
    SInt16      bitsPerSample;      // sampleSize (8 or 16), also two's-complement for 16-bit, offset for 8-bit
    UInt32      dataChunkID;        // 'data'
    UInt32      dataChunkSize;
} WaveHeader;

int tfChannels = 1; // mono
int tfSampleRate = 44100;
int tfBitsPerSample = 16;

WaveHeader *header = [maindata mutableBytes];

header->riffChunkID = CFSwapInt32HostToBig ('RIFF');
header->fileLength = CFSwapInt32HostToLittle ([maindata length] - 8);
header->waveFileID = CFSwapInt32HostToBig ('WAVE');

header->formatChunkID = CFSwapInt32HostToBig ('fmt ');
header->formatChunkSize = CFSwapInt32HostToLittle (16);
header->formatTag = CFSwapInt16HostToLittle (1);
header->channels = CFSwapInt16HostToLittle (tfChannels);
header->sampleRate = CFSwapInt32HostToLittle (tfSampleRate);
header->bytesPerSec = CFSwapInt32HostToLittle (tfSampleRate * tfBitsPerSample / 8 * tfChannels);
header->blockAlign = CFSwapInt16HostToLittle (tfBitsPerSample / 8 * tfChannels);
header->bitsPerSample = CFSwapInt16HostToLittle (tfBitsPerSample);
header->dataChunkID = CFSwapInt32HostToBig ('data');
header->dataChunkSize = CFSwapInt32HostToLittle ([maindata length] - 44);

短得多。希望这能有所帮助。

感谢您的快速回复。。我也会尝试集成CFByteOrder实用程序..嗨,Lucius,你的答案听起来很有趣,也很有帮助。我是iphone开发的新手,我正在做一个项目,在这个项目中我需要组合2个或更多的音频块。我正在提取所有标题和数据。我有所有的声音数据,需要根据数据重新写入标题。但是我在你的代码中没有得到什么东西。WaveHeader*header=[maindata可变字节];中的“maindata”是什么;。我该如何继续?提前感谢。
NSMutableData*maindata=[NSMutableData dataWithLength:sizeof(WaveHeader);
因此maindata是一个NSMutableData实例,即wave header的长度,用零填充。
typedef struct {
    UInt32      riffChunkID;        // Always RIFF, in big endian. Integer fields are little-ending.
    UInt32      fileLength;
    UInt32      waveFileID;     // 'WAVE' for Wave files.
    UInt32      formatChunkID;  // 'fmt '
    UInt32      formatChunkSize;
    SInt16      formatTag;          // Wave Format ID: see constants
    SInt16      channels;           // Number of Channels: 1=mono, 2=stereo
    SInt32      sampleRate;         // Sample Rate: samples per second
    SInt32      bytesPerSec;        // sampleRate * blockAlign
    SInt16      blockAlign;         // sample frame size = channels * sampleSize / 8
    SInt16      bitsPerSample;      // sampleSize (8 or 16), also two's-complement for 16-bit, offset for 8-bit
    UInt32      dataChunkID;        // 'data'
    UInt32      dataChunkSize;
} WaveHeader;

int tfChannels = 1; // mono
int tfSampleRate = 44100;
int tfBitsPerSample = 16;

WaveHeader *header = [maindata mutableBytes];

header->riffChunkID = CFSwapInt32HostToBig ('RIFF');
header->fileLength = CFSwapInt32HostToLittle ([maindata length] - 8);
header->waveFileID = CFSwapInt32HostToBig ('WAVE');

header->formatChunkID = CFSwapInt32HostToBig ('fmt ');
header->formatChunkSize = CFSwapInt32HostToLittle (16);
header->formatTag = CFSwapInt16HostToLittle (1);
header->channels = CFSwapInt16HostToLittle (tfChannels);
header->sampleRate = CFSwapInt32HostToLittle (tfSampleRate);
header->bytesPerSec = CFSwapInt32HostToLittle (tfSampleRate * tfBitsPerSample / 8 * tfChannels);
header->blockAlign = CFSwapInt16HostToLittle (tfBitsPerSample / 8 * tfChannels);
header->bitsPerSample = CFSwapInt16HostToLittle (tfBitsPerSample);
header->dataChunkID = CFSwapInt32HostToBig ('data');
header->dataChunkSize = CFSwapInt32HostToLittle ([maindata length] - 44);