How to save the audio recorded with pitch changed? - objective-c

I'm working on recording the voice then change the pitch of the audio and save.
I call this method after recording the voice and click on the button to change the pitch then the new file is also created but the not not able to listen the audio the audio is generated with out voice what may be the error?
-(void)saveEffectedAudioToFolder
{
NSError *error;
if (_audioEngine) {
AVAudioUnitTimePitch *pitchEffect = [AVAudioUnitTimePitch new];
pitchEffect.pitch = pitch;
AVAudioFormat * commonFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:44100 channels:2 interleaved:NO];
//
AVAudioFile *outputFile = [[AVAudioFile alloc] initForWriting:[NSURL URLWithString:_filePathDstaud] settings:commonFormat.settings error:&error];
if (error) {
NSLog(#"Error is 1 %#",[error localizedDescription]);
}
[pitchEffect installTapOnBus: 0 bufferSize: 8192 format: commonFormat block: ^(AVAudioPCMBuffer *buffer, AVAudioTime *when)
//here is that error
{
if (outputFile.length < _audioFile.length)
{
//Let us know when to stop saving the file, otherwise saving infinitely
NSError *error;
NSAssert([outputFile writeFromBuffer:buffer error:&error], #"error writing buffer data to file, %#", [error localizedDescription]);
}else{
_audioEngine = nil;
[pitchEffect removeTapOnBus:0];//if we dont remove it, will keep on tapping infinitely
NSLog(#"Did you like it? Please, vote up for my question");
}
}
];
}
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:name];
[fileManager removeItemAtPath:filePath error:&error];
}

Related

iCloud Drive - Read & Write (NSData)

Trying to save custom objects as NSData then upload to iCloud Drive
any direction?
I tried already the Key-Value Method, but it is limited for 1MB :/
is it the correct way?
if yes, how can I read from the iCloud path?
+(void)iCloudWrite:(NSData*)data
{
NSURL* ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:#"Documents"] URLByAppendingPathComponent:#"iCloudHistory.zip"];
MyDocument *mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
mydoc.dataContent = data;
[mydoc saveToURL:[mydoc fileURL] forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success)
{
if (success)
{
NSLog(#"Synced with icloud");
}
else
NSLog(#"Syncing FAILED with icloud");
}];
}
EDITED:
// 1. Any file can be uploaded to iCloud container of any size (yes you should be having that much of space in iCloud) lets take an example SampleData.zip
// 2. This method will upload or sync SampleData.zip file in iCloud container, iCloud actually checks the metadata of your file before it uploads it into your iCloud container (so for first time it will upload the file and from next time it will only upload the changes)
-(void) iCloudSyncing:(id)sender
{
//Doc dir
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"SampleData.zip"];
NSURL *u = [[NSURL alloc] initFileURLWithPath:filePath];
NSData *data = [[NSData alloc] initWithContentsOfURL:u];
//Get iCloud container URL
NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];// in place of nil you can add your container name
//Create Document dir in iCloud container and upload/sync SampleData.zip
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:#"Documents"]URLByAppendingPathComponent:#"SampleData.zip"];
Mydoc = [[MyDocument alloc] initWithFileURL:ubiquitousPackage];
Mydoc.zipDataContent = data;
[Mydoc saveToURL:[Mydoc fileURL] forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
{
if (success)
{
NSLog(#"SampleData.zip: Synced with icloud");
}
else
NSLog(#"SampleData.zip: Syncing FAILED with icloud");
}];
}
// 3 Download data from the iCloud Container
- (IBAction)GetData:(id)sender {
//--------------------------Get data back from iCloud -----------------------------//
id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
if (token == nil)
{
NSLog(#"ICloud Is not LogIn");
}
else
{
NSLog(#"ICloud Is LogIn");
NSError *error = nil;
NSURL *ubiq = [[NSFileManager defaultManager]URLForUbiquityContainerIdentifier:nil];// in place of nil you can add your container name
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:#"Documents"]URLByAppendingPathComponent:#"SampleData.zip"];
BOOL isFileDounloaded = [[NSFileManager defaultManager]startDownloadingUbiquitousItemAtURL:ubiquitousPackage error:&error];
if (isFileDounloaded) {
NSLog(#"%d",isFileDounloaded);
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//changing the file name as SampleData.zip is already present in doc directory which we have used for upload
NSString* fileName = [NSString stringWithFormat:#"RecSampleData.zip"];
NSString* fileAtPath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSData *dataFile = [NSData dataWithContentsOfURL:ubiquitousPackage];
BOOL fileStatus = [dataFile writeToFile:fileAtPath atomically:NO];
if (fileStatus) {
NSLog(#"success");
}
}
else{
NSLog(#"%d",isFileDounloaded);
}
}
}
//4 voila its done :)
Don't forget to add following parameters to your plist
<key>NSUbiquitousContainers</key>
<dict>
<key>YourCloudContainerID</key>
<dict>
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
<true/>
<key>NSUbiquitousContainerName</key>
<string>YourCloudContainerName</string>
<key>NSUbiquitousContainerSupportedFolderLevels</key>
<string>Any</string>
</dict>
</dict>

Play Last recording in Watchkit OS 2

i use the sample codes from apple for recording and playing the last recording
but i can't play the last recording
here are the codes
- (IBAction)playLastRecording {
// Present the media player controller for the last recorded URL.
NSDictionary *options = #{
WKMediaPlayerControllerOptionsAutoplayKey : #YES
};
[self presentMediaPlayerControllerWithURL:self.lastRecordingURL options:options completion:^(BOOL didPlayToEnd, NSTimeInterval endTime, NSError * __nullable error) {
if (!didPlayToEnd) {
NSLog(#"The player did not play all the way to the end. The player only played until time - %.2f.", endTime);
}
if (error) {
NSLog(#"There was an error with playback: %#.", error);
}
}];
}
and here is the error
i think we need to use the NSbundle and nsurl connection but how
to use for self.lastRecordingURL
please writing the correct codes for this problems
Optional(Error Domain=com.apple.watchkit.errors Code=4 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (1), NSUnderlyingError=0x17d9bf50 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}, NSLocalizedDescription=The operation could not be completed})
I had this problem. Make sure that the audio data is saved to the Apps Group correctly with the correct extension of the file.
If you are trying to record the audio file use the following codes.
- (void)startRecording
{
// Creating a path for saving the recorded audio file.
// We have to write the files to the shared group folder, as this is the only place both the app and extension can see.
NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
NSURL *outputURL = [container URLByAppendingPathComponent:#"AudioFile.m4a"];
// Setting the recorder options.
NSDictionary *dictMaxAudioRec = #{#"WKAudioRecorderControllerOptionsMaximumDurationKey":MAX_REC_DURATION};
// Presenting the default audio recorder.
[self presentAudioRecorderControllerWithOutputURL:outputURL preset:WKAudioRecorderPresetWideBandSpeech options:dictMaxAudioRec completion:^(BOOL didSave, NSError * error) {
if(didSave)
{
// Successfully saved the file.
NSURL *extensionDirectory = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask].firstObject;
NSUInteger timeAtRecording = (NSUInteger)[NSDate timeIntervalSinceReferenceDate];
NSString *dirName = [NSString stringWithFormat:#"AudioFile%d/",timeAtRecording];
NSURL *outputExtensionURL = [extensionDirectory URLByAppendingPathComponent:dirName];
// Move the file to new directory.
NSError *moveError;
BOOL success = [[NSFileManager defaultManager] moveItemAtURL:outputURL toURL:outputExtensionURL error:&moveError];
if (!success) {
NSLog(#"Failed to move the outputURL to the extension's documents direcotry: %#", moveError);
}
else {
NSData *audioData = [NSData dataWithContentsOfURL:outputExtensionURL];
NSLog(#"Actual Audio Data length: %lu", (unsigned long)audioData.length);
if(audioData.length)
{
// We have a valid audio data,do what ever you want to do with this data
}
}
}
else
{
// Something went wrong.
NSLog(#"%s - %#",__PRETTY_FUNCTION__,error);
}
}];
}
Or if you are trying to play a video that you have downloaded from other source or passed from the paired phone, write the audio data first to the App Groups with file extension. The following codes may help you for that.
- (void)writeAudioToAppGroupsWithData:(NSData *)audioData
{
// Writing the audio data to the App Groups
NSURL *containerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
containerURL = [containerURL URLByAppendingPathComponent:[NSString stringWithFormat:DIRECTORY_PATH]];
[audioData writeToURL:containerURL atomically:YES];
}
In this case make sure that your DIRECTORY_PATH is Library/Caches/filename.extension.
Eg: Library/Caches/Audio.mp3
For playing the saved audio use the following codes.
- (void)playAudio
{
// Playing the audio from the url using the default controller
[self presentMediaPlayerControllerWithURL:[self getAudioUrl] options:nil completion:^(BOOL didPlayToEnd, NSTimeInterval endTime, NSError * _Nullable error) {
NSLog(#"Error = %#",error);
}];
}
You can get the audio url from the App Groups.
- (NSURL *)getAudioUrl
{
// Getting the audio url from the App Groups
NSURL *container = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:APP_GROUP_IDENTIFIER];
NSURL *outputURL = [container URLByAppendingPathComponent:[NSString stringWithFormat:DIRECTORY_PATH]];
return outputURL;
}
Hope this will fix your issue.

How to download a file from a URL in OS X app

How do I download a file from a URL in an OS X app? I am a Unix C and Perl programmer new to Objective C. I've been reading the URL Loading System Programming Guide, which suggests NSURLSession for new OS X apps. So I'd prefer a solution with NSURLSession or NSURLSeesionDownloadTask, but am open to NSURLDownload or other solutions.
My first attempt was based an example found here
NSURLSessionDownloadTask *downloadTask =
[[NSURLSession sharedSession]
downloadTaskWithURL:[NSURL URLWithString:pdfFile]
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// move tmp file to permanent location
NSLog(#"Done...");
NSLog(#"Location: %#", location);
NSLog(#"Response: %#", response);
NSLog(#"Error %#", error);
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:[appDir stringByAppendingString:#"/demo.pdf"] error:&error];
NSLog(fileCopied ? #"File Copied OK" : #"ERROR Copying file.");
}];
[downloadTask resume];
NSLog(#"Now we are here");
The example code (and my version) don't have a separate delegate. The completionHandler is "in line". (Not sure if that's the correct terminology). I assume this code would be executed AFTER the download task completes. Is that correct?
My second attempt was based on the "Downloading Files" section of the URL Programming Guide:
// PDF file Download, try #2
NSError *error = nil;
NSString *appDir = NSHomeDirectory();
NSString *pdfFile = #"https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/AppDistributionGuide.pdf";
// Configure Cache behavior for default session
NSURLSessionConfiguration
*defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSString *cachePath = [NSTemporaryDirectory()
stringByAppendingPathComponent:#"/pdfDownload.cache"];
NSLog(#"Cache path: %#\n", cachePath);
NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384
diskCapacity: 268435456 diskPath: cachePath];
defaultConfigObject.URLCache = myCache;
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
defaultConfigObject.timeoutIntervalForRequest = 100;
defaultConfigObject.timeoutIntervalForResource = 100;
// Create a delegate-Free Session
NSURLSession *delegateFreeSession =
[NSURLSession sessionWithConfiguration: defaultConfigObject
delegate: nil
delegateQueue: [NSOperationQueue mainQueue]];
[[delegateFreeSession downloadTaskWithURL:[NSURL URLWithString:pdfFile] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// move tmp file to permanent location
NSLog(#"Done...");
NSLog(#"Location: %#", location);
NSLog(#"Response: %#", response);
NSLog(#"Error %#", error);
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileCopied = [fileManager moveItemAtPath:[location path] toPath:[appDir stringByAppendingString:#"/demo.pdf"] error:&error];
NSLog(fileCopied ? #"File Copied OK" : #"ERROR Copying file.");
}] resume];
sleep(10);
NSLog(#"After sleep...");
In both cases, code execution never gets to the NSLog statements that are part of the completionHandler. I have breakpoints set in the simulator, and never get there. How do I create a simple "delegate free" file download method?
Since I am writing a "command line" OS X app, I don't have a UIViewController, or other existing structure for delegates.
Any suggestions on how to proceed? I don't need a download progress bar, etc., just a "pass/fail" status.
Also, my example here is for a single PDF file. My app has an array of URLs that I'd like to download. I don't need to download them in parallel. Could I reuse a single NSURLSession in a loop?
Any help would be appreciated!!
Forgot to close this once I got the solution. As Zev pointed out, the PDF file I chose was large, and needed more time to download. The 10 second 'sleep(10)' didn't provide enough time to download the 39 MB file.
Notifications should be used to indicate when the completionHandler finishes. But for now, I am using a simple polling loop. I changed sleep(10); to
int timeoutCounter = 60;
while ((timeoutCounter > 0) && !downloadDone) {
sleep(1);
NSLog(#"Timout: %d", timeoutCounter--);
}
if (!downloadDone) {
NSLog(#"ERROR: Timeout occurred before file completed downloading");
}
This requires the declaration of downloadDone to allow the completionHandler block to set it:
__block BOOL downloadDone = FALSE;
After the NSFileManger moves the file, this semaphore must be set:
downloadDone = TRUE;
Thanks again for the help Zev!
I'm still working on error checking/handling, but here is the full corrected method:
+ (NSError *) downloadFileAtURL:(NSString *)fileURL
toDir:(NSString *)toDir
timeout:(NSNumber *)timeout {
// completion handler semaphore to indicate download is done
__block BOOL downloadDone = FALSE;
// same PDF file name for later
NSString *downloadFileName = [fileURL lastPathComponent];
NSString *finalFilePath = [toDir stringByAppendingPathComponent:downloadFileName];
NSLog(#"PDF file name: '%#'", downloadFileName);
NSLog(#"Final file path: '%#'", finalFilePath);
// Configure Cache behavior for default session
NSURLSessionConfiguration
*defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSString *cachePath = [NSTemporaryDirectory()
stringByAppendingPathComponent:#"/downloadFileCache"];
NSLog(#"Cache path: %#\n", cachePath);
NSURLCache *myCache = [[NSURLCache alloc] initWithMemoryCapacity: 16384
diskCapacity: 268435456 diskPath: cachePath];
defaultConfigObject.URLCache = myCache;
defaultConfigObject.requestCachePolicy = NSURLRequestUseProtocolCachePolicy;
defaultConfigObject.timeoutIntervalForRequest = 100;
defaultConfigObject.timeoutIntervalForResource = 100;
// Create a delegate-Free Session
// delegateQueue: [NSOperationQueue mainQueue]];
NSURLSession *delegateFreeSession =
[NSURLSession sessionWithConfiguration: defaultConfigObject
delegate: nil
delegateQueue: nil];
[[delegateFreeSession downloadTaskWithURL:[NSURL URLWithString:fileURL] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// move tmp file to permanent location
NSLog(#"In the completion handler...");
NSLog(#"Location: %#", location);
NSLog(#"Response: %#", response);
NSLog(#"Error %#", error);
NSLog(#"Location path: %#", [location path]);
// Verify temp file exists in cache
NSFileManager *fileManager = [[NSFileManager alloc] init];
if ( [fileManager fileExistsAtPath:[location path]]) {
NSLog(#"File exists. Now move it!");
error = nil;
BOOL fileCopied = [fileManager moveItemAtPath:[location path]
toPath:finalFilePath
error:&error];
NSLog(#"Error: %#", error);
NSLog(fileCopied ? #"File Copied OK" : #"ERROR Copying file.");
}
downloadDone = TRUE;
}] resume];
// use timeout argument
int timeoutCounter = [timeout intValue];
while ((timeoutCounter > 0) && !downloadDone) {
sleep(1);
NSLog(#"Timout: %d", timeoutCounter--);
}
if (!downloadDone) {
NSLog(#"ERROR: Timeout occurred before file completed downloading");
}
NSError *error = nil;
return error;
}

How to Upload file to google drive only if it is not exist?

I use xcode to develope iphone application.
i upload Database files to my google drive with this code.
- (void)uploadDB{
GTLDriveFile *file = [GTLDriveFile object];
file.title = [NSString stringWithFormat:#"User:%#DB.sqlite",UserName];
file.descriptionProperty = #"Uploaded from iOS ";
file.mimeType = #"application/x-sqlite3";
// Attach a DB file to the email
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/%#",
documentsDirectory,DB_File];
NSData *data = [NSData dataWithContentsOfFile:fileName];
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:file.mimeType];
GTLQueryDrive *query = [GTLQueryDrive queryForFilesInsertWithObject:file
uploadParameters:uploadParameters];
UIAlertView *waitIndicator = [self showWaitIndicator:#"Uploading to Google Drive"];
[self.driveService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *insertedFile, NSError *error) {
[waitIndicator dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil)
{
NSLog(#"File ID: %#", insertedFile.identifier);
[self showAlert:#"Google Drive" message:#"File saved!"];
}
else
{
NSLog(#"An error occurred: %#", error);
[self showAlert:#"Google Drive" message:#"Sorry, an error occurred!"];
}
}];
}
My problem that it is always save it as a new file, I wand that it will check if this file name exist on drive and replace it.
Thanks
The title of a file in Drive is not unique. Instead, you should use the resource id. The first time you upload the database file, remember the resource id that it gives back to you on success and then update that from then on.

AVFoundation video capture won't save

I am using AVFoundation to capture video. All seems to be well in my app until I get to here:
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
NSLog(#"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
{
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
{
RecordedSuccessfully = [value boolValue];
}
}
if (RecordedSuccessfully)
{
//----- RECORDED SUCESSFULLY -----
NSLog(#"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
}
}];
}
[library release];
}
}
When running it on a device I receive the "didFinishRecordingToOutputFileAtURL - success" message, and then it crashes and I get this error:
Video /private/var/mobile/Applications/EDC62CED-3710-45B2-A658-A2FE9238F517/tmp/output.mov cannot be saved to the saved photos album: Error Domain=NSOSStatusErrorDomain Code=-12950 "Movie could not be played." UserInfo=0xe6749b0 {NSLocalizedDescription=Movie could not be played.}
I haven't been able to find a whole lot of information about this anywhere and am not really sure what's going on.
Here's the code with the temporary output URL:
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output.mov"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
{
//Error - handle if requried
}
}
[outputPath release];
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
[outputURL release];
I've already tried releasing the outputURL elsewhere after it saves, and that didn't help, so I don't think that's it.
I figured this out. I was an idiot and kept overlooking the fact that I didn't actually connect the video input to the capture session. Whoops.