Я создаю приложение для iPhone, которое позволяет пользователю создавать аудиофильтр и тестировать его на некоторый записанный звук. Я пытаюсь сделать следующее:
- Я создаю два аудиофайла, которые называются "recorddeAudio.aiff" и "FilterAudio.aiff"
- Я записываю звук с микрофона и сохраняю его в "записанный аудио.афф"
- Я копирую аудиоданные из "recordsAudio.aiff" в буфер
- Позже я выполню некоторую аудио-фильтрацию данных, находящихся в буфере на этом этапе, но для целей тестирования я просто хочу уменьшить значение каждого семпла вдвое (что просто уменьшит громкость вдвое) так что я уверен, что могу манипулировать единичными выборками
- Я записываю результат во второй буфер
- Я записываю данные этого буфера во второй файл «FilterAudio.aiff»
- Я играю второй файл
Проблема в следующем: до тех пор, пока я просто копирую данные из одного буфера в другой, а затем записываю их во второй аудиофайл, все работает нормально. Но как только я пытаюсь выполнить какую-либо операцию над семплами (например, разделить их на 2), результатом будет просто случайный шум. Это заставляет меня подозревать, что я неправильно интерпретирую значения аудиоданных, но я пытался в течение пяти дней, и я просто не понимаю. Если у вас есть идеи, как можно получить доступ и управлять отдельными аудиосэмплами, помогите мне с этим, я был бы очень признателен!
Спасибо!
Это код, который будет выполнять фильтрацию позже (сейчас он должен просто делить все аудиосэмплы на 2);
OSStatus status = noErr;
UInt32 propertySizeDataPacketCount;
UInt32 writabilityDataPacketCount;
UInt32 numberOfPackets;
UInt32 propertySizeMaxPacketSize;
UInt32 writabilityMaxPacketSize;
UInt32 maxPacketSize;
UInt32 numberOfBytesRead;
UInt32 numberOfBytesToWrite;
UInt32 propertySizeDataByteCount;
SInt64 currentPacket;
double x0;
double x1;
status = AudioFileOpenURL(audioFiles->recordedFile,
kAudioFileReadPermission,
kAudioFileAIFFType,
&audioFiles->inputFile);
status = AudioFileOpenURL(audioFiles->filteredFile,
kAudioFileReadWritePermission,
kAudioFileAIFFType,
&audioFiles->outputFile);
status = AudioFileGetPropertyInfo(audioFiles->inputFile,
kAudioFilePropertyAudioDataPacketCount,
&propertySizeDataPacketCount,
&writabilityDataPacketCount);
status = AudioFileGetProperty(audioFiles->inputFile,
kAudioFilePropertyAudioDataPacketCount,
&propertySizeDataPacketCount,
&numberOfPackets);
status = AudioFileGetPropertyInfo (audioFiles->inputFile,
kAudioFilePropertyMaximumPacketSize,
&propertySizeMaxPacketSize,
&writabilityMaxPacketSize);
status = AudioFileGetProperty(audioFiles->inputFile,
kAudioFilePropertyMaximumPacketSize,
&propertySizeMaxPacketSize,
&maxPacketSize);
SInt16 *inputBuffer = (SInt16 *)malloc(numberOfPackets * maxPacketSize);
SInt16 *outputBuffer = (SInt16 *)malloc(numberOfPackets * maxPacketSize);
currentPacket = 0;
status = AudioFileReadPackets(audioFiles->inputFile,
false, &numberOfBytesRead,
NULL,
currentPacket,
&numberOfPackets,
inputBuffer);
for (int i = 0; i < numberOfPackets; i++) {
x0 = (double)inputBuffer[i];
x1 = 0.5 * x0; //This is supposed to reduce the value of the sample by half
//x1 = x0; //This just copies the value of the sample and works fine
outputBuffer[i] = (SInt16)x1;
}
numberOfBytesToWrite = numberOfBytesRead;
currentPacket = 0;
status = AudioFileWritePackets(audioFiles->outputFile,
false,
numberOfBytesToWrite,
NULL,
currentPacket,
&numberOfPackets,
outputBuffer);
status = AudioFileClose(audioFiles->inputFile);
status = AudioFileClose(audioFiles->outputFile);
Для создания аудиофайлов я использую следующий код:
#import "AudioFiles.h"
#define SAMPLE_RATE 44100
#define FRAMES_PER_PACKET 1
#define CHANNELS_PER_FRAME 1
#define BYTES_PER_FRAME 2
#define BYTES_PER_PACKET 2
#define BITS_PER_CHANNEL 16
@implementation AudioFiles
-(void)setupAudioFormat:(AudioStreamBasicDescription *)format {
format->mSampleRate = SAMPLE_RATE;
format->mFormatID = kAudioFormatLinearPCM;
format->mFramesPerPacket = FRAMES_PER_PACKET;
format->mChannelsPerFrame = CHANNELS_PER_FRAME;
format->mBytesPerFrame = BYTES_PER_FRAME;
format->mBytesPerPacket = BYTES_PER_PACKET;
format->mBitsPerChannel = BITS_PER_CHANNEL;
format->mReserved = 0;
format->mFormatFlags = kLinearPCMFormatFlagIsBigEndian |
kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
}
- (id)init
{
self = [super init];
if (self) {
char path[256];
NSArray *dirPaths;
NSString *docsDir;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *recordedFilePath = [docsDir stringByAppendingPathComponent:@"/recordedAudio.aiff"];
[recordedFilePath getCString:path maxLength:sizeof(path) encoding:NSUTF8StringEncoding];
recordedFile = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)path, strlen(path), false);
recordedFileURL = [NSURL fileURLWithPath:recordedFilePath];
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
NSString *filteredFilePath = [docsDir stringByAppendingPathComponent:@"/filteredAudio.aiff"];
[filteredFilePath getCString:path maxLength:sizeof(path) encoding:NSUTF8StringEncoding];
filteredFile = CFURLCreateFromFileSystemRepresentation(NULL, (UInt8 *)path, strlen(path), false);
filteredFileURL = [NSURL fileURLWithPath:filteredFilePath];
AudioStreamBasicDescription audioFileFormat;
[self setupAudioFormat:&audioFileFormat];
OSStatus status = noErr;
status = AudioFileCreateWithURL(recordedFile,
kAudioFileAIFFType,
&audioFileFormat,
kAudioFileFlags_EraseFile,
&inputFile);
status = AudioFileCreateWithURL(filteredFile,
kAudioFileAIFFType,
&audioFileFormat,
kAudioFileFlags_EraseFile,
&outputFile);
}
return self;
}
@end
Для записи я использую AVAudioRecorder со следующими настройками:
NSDictionary *recordSettings =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithFloat: 8000.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithBool:YES],AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:YES], AVLinearPCMIsNonInterleaved,
nil];
NSError *error = nil;
audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFiles->recordedFileURL settings:recordSettings error:&error];
if (error)
{
NSLog(@"error: %@", [error localizedDescription]);
} else {
[audioRecorder prepareToRecord];
}