How to convert WAV file to M4A? - ios

Is there any way to convert my recorded .WAV file to .M4A file in iOS?
And also I have to convert .M4A file to .WAV file.
I tried with Audio Queue Services, but I am not able to do.

This post: From iPod Library to PCM Samples in Far Fewer Steps Than Were Previously Necessary describes how to load a file from the users ipod library and write it to the file system as a linear pcm (wav) file.
I believe that the change that you will need to make to the code to load a file from the file system instead would be in the NSURL that describes where the asset is:
-(IBAction) convertTapped: (id) sender {
// set up an AVAssetReader to read from the iPod Library
NSURL *assetURL = [[NSURL alloc] initFileURLWithPath:#"your_m4a.m4a"];
AVURLAsset *songAsset =
[AVURLAsset URLAssetWithURL:assetURL options:nil];
NSError *assetError = nil;
AVAssetReader *assetReader =
[[AVAssetReader assetReaderWithAsset:songAsset
error:&assetError]
retain];
if (assetError) {
NSLog (#"error: %#", assetError);
return;
}
If you are going in the opposite direction, you will need to change the formatting on the output end:
NSDictionary *outputSettings =[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:2], AVNumberOfChannelsKey,
[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)],
AVChannelLayoutKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil];
I am not sure of the exact settings that would go in here for m4a, but this should get you closer.
The other option would be to load in ffmpeg lib and do all your conversion in there, but that seems like different than what you want.

TPAACAudioConverter works fine

Related

How to specify fmt chunk in .wav header with Objective-C

My iPhone app works well in iOS10 but doesn't work in iOS11. This app records user's voice as .wav file but its header data seems to be different between iOS10 and iOS11. The wave file is outputted using "fmt chunk" in iOS10 but "JUNK chunk" in iOS11. I need to specify fmt chunk in the header.
Here is the code to output wave file.
// Create file path.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yMMddHHmmss"];
NSString *fileName = [NSString stringWithFormat:#"%#.wav", [formatter stringFromDate:[NSDate date]]];
self.filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
// Change Audio category to Record.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryRecord error:nil];
// Settings for AVAAudioRecorder.
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithUnsignedInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:16000.0], AVSampleRateKey,
[NSNumber numberWithUnsignedInt:1], AVNumberOfChannelsKey,
[NSNumber numberWithUnsignedInt:16], AVLinearPCMBitDepthKey,
nil];
self.recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL URLWithString:filePath] settings:settings error:nil];
recorder.delegate = self;
[recorder prepareToRecord];
[recorder record];
I really need your help. Thank you.
I've solved this issue thanks to this post.
Audio file format issue in objective c
Thank you.

AVAssetWriterInput does not currently support AVVideoScalingModeFit - IOS Error

I'm attempting to use the AVAssetWriterInput to crop a video that I read in a screencast of my application. Here is my current configuration.
NSDictionary *videoCleanApertureSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:320], AVVideoCleanApertureWidthKey,
[NSNumber numberWithInt:480], AVVideoCleanApertureHeightKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureHorizontalOffsetKey,
[NSNumber numberWithInt:10], AVVideoCleanApertureVerticalOffsetKey,
nil];
NSDictionary *videoAspectRatioSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:3], AVVideoPixelAspectRatioHorizontalSpacingKey,
[NSNumber numberWithInt:3],AVVideoPixelAspectRatioVerticalSpacingKey,
nil];
NSDictionary *codecSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:960000], AVVideoAverageBitRateKey,
[NSNumber numberWithInt:1],AVVideoMaxKeyFrameIntervalKey,
videoCleanApertureSettings, AVVideoCleanApertureKey,
videoAspectRatioSettings, AVVideoPixelAspectRatioKey,
AVVideoProfileLevelH264BaselineAutoLevel, AVVideoProfileLevelKey,
nil];
NSDictionary *videoSettings = #{AVVideoCodecKey:AVVideoCodecH264,
AVVideoCompressionPropertiesKey:codecSettings,
AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill,
AVVideoWidthKey:[NSNumber numberWithInt:320],
AVVideoHeightKey:[NSNumber numberWithInt:480]};
_videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings];
I'm receiving the following error: "AVAssetWriterInput does not currently support AVVideoScalingModeFit"
This is a common error for anyone using this library, but I can't find the actual solution to it. I just see people saying: "I figured it out eventually" without explaining it. The problem is definitely related to this line: "AVVideoScalingModeKey:AVVideoScalingModeResizeAspectFill," which tells the AVAssetWriter to crop the video and maintain the aspect ratio. Anyone know the solution to this?
There is no "solution to it" per se. It's simply unsupported. You'll need to scale the video frames yourself using Core Image or a VTPixelTransferSession or whatever is appropriate for your pipeline.

Audio which is recorded in iOS programmatically could not be playable in Windows

Scenario: The App which I am working on I am suppose to recored voice memos and send them to the Windows client. Recording audio in iOS is not that much hard but the recorded file (in my case in the form of .mp3) could not be playable in Windows but the same file could be easily playable in Mac.
I strongly suspect on my audio recording settings which I am using in the following code,
_audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioFileURL settings:_recordingSettings error:&error];
and the settings that I am using is,
_recordingSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithInt: 2], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
nil];
I have already tried the various AVFormatIDKeys such as
kAudioFormatLinearPCM - .lpcm
kAudioFormatMPEG4AAC - .acc
kAudioFormatMPEGLayer3 - .mp3
but no gain.
I appreciate any help. In case if it is not possible I need the explanation why!
After some random tries I have managed myself with the settings,
_recordingSettings = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
[NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO],AVLinearPCMIsNonInterleaved,
[NSNumber numberWithInt:AVAudioQualityMin], AVEncoderAudioQualityKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:2000.0], AVSampleRateKey,
nil];
Important: The filename should be "someName.wav"

AVAudioRecorder not saving recording to path specified

I am recording audio using AVAudioRecorder it is recording smoothly and i can play or get the save file I am using following code to initialize AVAudioRecorder
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithInt:AVAudioQualityLow], AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16], AVEncoderBitRateKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithFloat:16000], AVSampleRateKey,
nil];
NSArray *searchPaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath_ = [searchPaths objectAtIndex: 0];
NSString *pathToSave = [documentPath_ stringByAppendingPathComponent:[self dateString]];
self.pathfinal = pathToSave;
NSURL *url = [NSURL fileURLWithPath:pathToSave];
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (!recorder)
{
return NO;
}
recorder.delegate = self;
recorder.meteringEnabled = YES;
if (![recorder prepareToRecord])
{
return NO;
}
if (![recorder record])
{
return NO;
}
but some of my clients are facing an issue when they stop the recorded (the step where it will save on disk) it does not save anything it creates the file but with no data every time they record.
But when using different iPhone it was not an issue. iPhone had 2gb free hard disk space. Any idea what could be causing that?
In my case, just try not to use AVEncoderBitRateKey will solve the problem.
See this question.
There is no need of AVEncoderBitRateKey to record AAC format audio. AAC is a low quality audio recording. AVEncoderBitRateKey is used to record high quality audio.

Is it possible to use AVAssetReader to get back a stereo channel layout?

I'd like to be able to get back AudioBufferList from AVAssetReader which has 2 buffers so that I can process the left and right audio through an AudioUnit. I tried using the output settings below but it will not read as long as I specify the stereo layout set by kAudioChannelLayoutTag_Stereo.
Is it possible for AVAssetReader to return a non-interleaved result?
If not, how would I convert it to a non-interleaved AudioBufferList? I have tried to use Audio Converter Services but I cannot get it to accept either the the input or output values for the AudioStreamBasicDescription. (ASBD) If I cannot get the data in the format I want from AVAssetReader I would like to at least be able to convert it to the format I need.
Any tips are appreciated.
- (NSDictionary *) getOutputSettings {
AudioChannelLayout channelLayout;
memset(&channelLayout, 0, sizeof(AudioChannelLayout));
channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
[NSNumber numberWithFloat:44100.0], AVSampleRateKey,
[NSNumber numberWithInt:2], AVNumberOfChannelsKey,
[NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,
[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
[NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
[NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,
nil];
return outputSettings;
}
I think that kAudioChannelLayoutTag_Stereo is requesting interleaved samples, so I'd lose it.
It all depends on what kind of AVAssetReaderOutput you're creating with those output settings. AVAssetReaderTrackOutput does no conversion beyond decoding to LPCM, but AVAssetReaderAudioMixOutput accepts a bunch more format keys, in fact it probably IS an AVAssetReaderTrackOutput + AudioConverter.
I've learned that I can have AVAssetReader return results with the default output settings (nil) which will give me an interleaved result of float values. The buffer of float values alternates from Left to Right through the buffer. I am able to work with these values which are in the range of -1.0 to 1.0 but in order to play the audio it is necessary to increase the values to the range of a short signed int, so I multiply them by SHRT_MAX and ensure the values stay within the range of SHRT_MAX and SHRT_MIN so the audio plays as expected.
Since the interleaved buffer returns the L and R values on the same buffer it is considered 2 channels on the 1 buffer which is reflected in the AudioBufferList. Previously I was able to get back 2 buffers with 1 channel per buffer but that is not really necessary now that I understand the very simple interleaved format.

Resources