gpt4 book ai didi

ios - 从 NSData 解码 MP3 文件

转载 作者:可可西里 更新时间:2023-11-01 03:58:20 29 4
gpt4 key购买 nike

对于我的应用程序,我需要解码存储在 NSData 对象中的 MP3 文件。

出于安全原因,将 NSData 对象写入磁盘并使用系统 URL 引用重新打开它是不可取的,即使它只在本地存储了片刻。

我想利用扩展音频文件服务(或音频文件服务)来执行此操作,但我无法获得 NSData 的表示,它仅存在于内存中,可以被这些音频文件读取服务。

编辑:我想解码 MP3 数据,这样我就可以访问线性 PCM 音频样本进行操作。从 NSData 对象回放不是问题。

我的代码如下:

 decryptedData; //an NSData object which has already been initialized
const void *dataBytes = decryptedData.bytes; //pointer to the bytes in my NSData object

//this creates a CFURLRef from the pointer to the byte data
//I have printed out the resulting CFURL and have confirmed that it is indeed reading the bytes correctly
CFURLRef audioFileURLFromBytes = CFURLCreateWithBytes (kCFAllocatorDefault,
dataBytes,
decryptedData.length,
kCFStringEncodingASCII,
NULL);

//attempt to open the the URL using Extended Audio File Services
ExtAudioFileRef outExtAudioFile;
OSStatus err = 0;
err = ExtAudioFileOpenURL(audioFileURLFromBytes, &outExtAudioFile);
if (err != noErr) {
NSLog(@"ExtAudioFileOpenURL failed with OSStatus Code %i \n", err);
}

//Attempt to open the URL using Audio File Services
AudioFileID audioFile;
OSStatus res = 0;
res = AudioFileOpenURL(audioFileURLFromBytes, kAudioFileReadPermission, kAudioFileMP3Type, &audioFile);
if (res != noErr) {
NSLog(@"AudioFileOpenURL failed with OSStatus Code %i \n", res);
}

两次打开 URL 的尝试都会导致 OSStatus 代码 43,即“找不到文件”。

我已验证我的指针指向 NSData 内存中的正确地址,并且可以正确读取字节。

扩展音频文件服务是否存在一些限制,禁止引用存储在内存中的字节?

感谢您提供的任何帮助。

编辑:我根据 Sbooth 的建议找到了解决方法。代码如下:此函数采用包含音频文件的 mp3 表示形式的 NSData 对象。它将其解码为线性 PCM,因此您可以获得样本,然后将其重新编码为 AAC。我不认为 MP3 编码在所有平台(移动/桌面)的 CoreAudio 中都可用。此代码已在我的 Mac 上进行了测试,可以完成工作。

-(void) audioFileReaderWithData: (NSData *) audioData {

AudioFileID refAudioFileID;
ExtAudioFileRef inputFileID;
ExtAudioFileRef outputFileID;

OSStatus result = AudioFileOpenWithCallbacks(audioData, readProc, 0, getSizeProc, 0, kAudioFileMP3Type, &refAudioFileID);
if(result != noErr){
NSLog(@"problem in theAudioFileReaderWithData function: result code %i \n", result);
}

result = ExtAudioFileWrapAudioFileID(refAudioFileID, false, &inputFileID);
if (result != noErr){
NSLog(@"problem in theAudioFileReaderWithData function Wraping the audio FileID: result code %i \n", result);
}

// Client Audio Format Description
AudioStreamBasicDescription clientFormat;
memset(&clientFormat, 0, sizeof(clientFormat));
clientFormat.mFormatID = kAudioFormatLinearPCM;
clientFormat.mFramesPerPacket = 1;
clientFormat.mChannelsPerFrame = 2;
clientFormat.mBitsPerChannel = 32;
clientFormat.mBytesPerPacket = clientFormat.mBytesPerFrame = 4 * clientFormat.mChannelsPerFrame;
clientFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
clientFormat.mSampleRate = 44100;

//Output Audio Format Description
AudioStreamBasicDescription outputFormat;
memset(&outputFormat, 0, sizeof(outputFormat));
outputFormat.mChannelsPerFrame = 2;
outputFormat.mSampleRate = 44100;
outputFormat.mFormatID = kAudioFormatMPEG4AAC;
outputFormat.mFormatFlags = kMPEG4Object_AAC_Main;
outputFormat.mBitsPerChannel = 0;
outputFormat.mBytesPerFrame = 0;
outputFormat.mBytesPerPacket = 0;
outputFormat.mFramesPerPacket = 1024;

// create the outputFile that we're writing to here....
UInt32 outputFormatSize = sizeof(outputFormat);
result = 0;
result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &outputFormatSize, &outputFormat);
if(result != noErr)
NSLog(@"could not set the output format with status code %i \n",result);

NSMutableString *outputFilePath = [NSMutableString stringWithCapacity: 100];
[outputFilePath setString:@"/Users/You/Desktop/testAudio.m4a"];
NSURL *sourceURL = [NSURL fileURLWithPath:outputFilePath];

result = 0;
result = ExtAudioFileCreateWithURL((CFURLRef)sourceURL, kAudioFileM4AType, &outputFormat, NULL, kAudioFileFlags_EraseFile, &outputFileID);
if(result != noErr){
NSLog(@"ExtAudioFileCreateWithURL failed for outputFileID with status %i \n", result);
}

int size = sizeof(clientFormat);
result = 0;
result = ExtAudioFileSetProperty(inputFileID, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);

if(result != noErr)
NSLog(@"error on ExtAudioFileSetProperty for input File with result code %i \n", result);

size = sizeof(clientFormat);
result = 0;
result = ExtAudioFileSetProperty(outputFileID, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat);
if(result != noErr)
NSLog(@"error on ExtAudioFileSetProperty for output File with result code %i \n", result);

int totalFrames = 0;
UInt32 outputFilePacketPosition = 0; //in bytes
UInt32 encodedBytes = 0;

while (1) {
UInt32 bufferByteSize = 22050 * 4 * 2;
char srcBuffer[bufferByteSize];
UInt32 numFrames = (bufferByteSize/clientFormat.mBytesPerFrame);

AudioBufferList fillBufList;
fillBufList.mNumberBuffers = 1;
fillBufList.mBuffers[0].mNumberChannels = clientFormat.mChannelsPerFrame;
fillBufList.mBuffers[0].mDataByteSize = bufferByteSize;
fillBufList.mBuffers[0].mData = srcBuffer;
result = 0;
result = ExtAudioFileRead(inputFileID, &numFrames, &fillBufList);

if (result != noErr) {
NSLog(@"Error on ExtAudioFileRead with result code %i \n", result);
totalFrames = 0;
break;
}
if (!numFrames)
break;

totalFrames = totalFrames + numFrames;

result = 0;
result = ExtAudioFileWrite(outputFileID,
numFrames,
&fillBufList);

if(result!= noErr){
NSLog(@"ExtAudioFileWrite failed with code %i \n", result);
}

encodedBytes += numFrames * clientFormat.mBytesPerFrame;
}

//Clean up

ExtAudioFileDispose(inputFileID);
ExtAudioFileDispose(outputFileID);
AudioFileClose(refAudioFileID);

}

您还需要这些功能...

static OSStatus readProc(void* clientData,
SInt64 position,
UInt32 requestCount,
void* buffer,
UInt32* actualCount)
{

NSData *inAudioData = (NSData *) clientData;

size_t dataSize = inAudioData.length;
size_t bytesToRead = 0;

if(position < dataSize) {
size_t bytesAvailable = dataSize - position;
bytesToRead = requestCount <= bytesAvailable ? requestCount : bytesAvailable;

[inAudioData getBytes: buffer range:NSMakeRange(position, bytesToRead)];
} else {
NSLog(@"data was not read \n");
bytesToRead = 0;
}

if(actualCount)
*actualCount = bytesToRead;

return noErr;
}

static SInt64 getSizeProc(void* clientData) {
NSData *inAudioData = (NSData *) clientData;
size_t dataSize = inAudioData.length;
return dataSize;
}

最佳答案

问题是您正在尝试使用 ASCII 编码从音频字节(MP3 帧)创建一个 CFURLRef 对象。 CFURLCreateWithBytes 旨在与字节字符串一起使用,而不是二进制数据(即“http://www.apple.com”作为 char *)。要完成您想要的操作,请使用 AudioFileOpenWithCallbacks,将您的 NSData 对象作为 refcon 传递,并在对 NSData 操作的自定义回调中处理原始读取/搜索> 你传入的。

关于ios - 从 NSData 解码 MP3 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17330135/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com