Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

ios - save the audio file in the background

I have an app that changes the pitch of the audio when the pitch button is selected, now i am using installTapOnBus to save the file but this method gets invocated after i press the pitch button therefore only part of the audio is saved, i want to save the whole audio no matter when the pitch button is selected, is there any way

This method is used to play the audio

-(void)playAudio
{
    NSError *err = nil;

    audioEngine = [[AVAudioEngine alloc] init];
    AudioFileplayer = [[AVAudioPlayerNode alloc] init];
    pitch = [[AVAudioUnitTimePitch alloc] init];
    reverb = [[AVAudioUnitReverb alloc] init];
    [audioEngine stop];
    [AudioFileplayer stop];
    [audioEngine reset];

    file = [[AVAudioFile alloc] initForReading:[NSURL URLWithString:[self filePath]] error:&err];


    [audioEngine attachNode:AudioFileplayer];

    [audioEngine attachNode:pitch];
    [audioEngine attachNode:reverb];

    [audioEngine connect:AudioFileplayer to:reverb format:nil];
    [audioEngine connect:reverb to:pitch format:nil];
    [audioEngine connect:pitch to:audioEngine.outputNode format:nil];
    [reverb loadFactoryPreset:AVAudioUnitReverbPresetLargeRoom2];

 [AudioFileplayer scheduleFile:file atTime:nil completionHandler:^{
        AudioFileplayer = nil;
    }];

    [audioEngine prepare];
    [audioEngine startAndReturnError:&err];

    if (err != nil) {
        NSLog(@"An error occured");
    }

    [AudioFileplayer play];



}

and this method to save the pitch effected audio

-(void)saveEffectedAudioToFolder
{
NSError *error;
if (audioEngine) {


     pitchEffect.pitch = 1000;

    AVAudioFormat  * commonFormat = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatFloat32 sampleRate:44100 channels:2 interleaved:NO];

    //
    AVAudioFile *outputFile = [[AVAudioFile alloc] initForWriting:[NSURL URLWithString:[self filePath1]] settings:commonFormat.settings error:&error];
    //


    if (error) {
        NSLog(@"Error is 1 %@",[error localizedDescription]);


    }
    [pitchEffect  installTapOnBus:0 bufferSize:4096 format:commonFormat block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when)
     {

         if (outputFile.length < file.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

         }

     }


     ];
}

}

any workaround would be helful

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually we made mistake in the settings of Output Audio File. The output audio file processing format should be same like as the input file(which u put effect or pitch).

And the Output file format should be in the wav or caf format. This format only save to the output audio file.

 - (IBAction)save_it_after_changes:(id)sender
    {

             engine = [[AVAudioEngine alloc] init];
             audio_player_node= [[AVAudioPlayerNode alloc] init];
            [engine attachNode:audio_player_node];
            [self setupEQ];

            AVAudioMixerNode *mixerNode = [engine mainMixerNode];
            [engine connect:audio_player_node to:unitEq format:audioFile.processingFormat];
            [engine connect:unitEq to:mixerNode format:audioFile.processingFormat];

            NSError *error12;
            [engine startAndReturnError:&error12];
            if (!error12)
            {
                  NSLog(@"Engine = %@",engine);
                 [audio_player_node scheduleFile:audioFile atTime:nil completionHandler:nil];
                 NSMutableDictionary *recordSetting = [[NSMutableDictionary alloc] init];

                  [recordSetting setValue :[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey];
                  [recordSetting setValue:[NSNumber numberWithFloat:44100.0] forKey:AVSampleRateKey];
                  [recordSetting setValue:[NSNumber numberWithInt: 2] forKey:AVNumberOfChannelsKey];

                  [recordSetting setValue :[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
                  [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey];
                  [recordSetting setValue :[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey];


                  NSError *error;
                 outputFile = [[AVAudioFile alloc] initForWriting:[self testFilePathURL] settings:recordSetting error:&error];
                  NSLog(@"outputfile = %@",outputFile);
                  if (error)
                  {
                         NSLog(@"outputFile error = %@",error);
                  }
                  else
                  { //(AVAudioFrameCount)audioFile.length
                        [audio_player_node installTapOnBus:0 bufferSize:8192  format:audioFile.processingFormat block:^(AVAudioPCMBuffer *buffer, AVAudioTime *when) {
                              NSLog(@"Buffer Size = %@",buffer);
                              NSLog(@"when = %lld",when.sampleTime);
                              NSLog(@"outputfile length = %lli",outputFile.length);
                              NSLog(@"input file length = %lld",audioFile.length);
                              if (outputFile.length<audioFile.length)
                              {
                                    NSError *error;
                                    [outputFile writeFromBuffer:buffer error:&error];
                                    if (error)
                                    {
                                          NSLog(@"writebuffererror =%@",error);
                                    }
                              }
                              else
                              {
                                    [audio_player_node removeTapOnBus:0];
                                     NSError *error2;
                                   // player2 = [[AVAudioPlayer alloc] initWithContentsOfURL:[self testFilePathURL] error:&error2];
                                    //player2.delegate = self;
                                    NSLog(@"Pathththt = %@",[self testFilePathURL]);
                                    NSLog(@"error = %@",error2);
                                   // [audio_player_node scheduleFile:outputFile atTime:nil completionHandler:nil];
                                    //[audio_player_node play];
                                   // [self toMp3];
                              }

                        }];
                  }
            }
            else
            {
                  NSLog(@"error12 =%@",error12);
            }

    }





- (void)setupEQ
{
      NSLog(@"setupEQ");

      unitEq = [[AVAudioUnitEQ alloc] initWithNumberOfBands:12];
      unitEq.globalGain = 3.0;
      AVAudioUnitEQFilterParameters *filterParameters;
      filterParameters = unitEq.bands[0];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 31;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[1];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 63;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[2];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 125;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[3];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 250;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[4];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 500;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[5];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 1000;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[6];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 2000;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[7];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 4000;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain =-20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[8];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 8000;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain = -20;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[9];
      filterParameters.filterType = AVAudioUnitEQFilterTypeParametric;
      filterParameters.frequency = 16000;
      filterParameters.bandwidth = 1.0;
      filterParameters.gain =-20;
      filterParameters.bypass = FALSE;


      filterParameters = unitEq.bands[10];
      filterParameters.filterType = AVAudioUnitEQFilterTypeLowPass;
      filterParameters.frequency = 16857;
      filterParameters.bypass = FALSE;

      filterParameters = unitEq.bands[11];
      filterParameters.filterType = AVAudioUnitEQFilterTypeHighPass;
      filterParameters.frequency = 205;
      filterParameters.bypass = FALSE;
      [engine attachNode:unitEq];
}




- (NSString *)applicationDocumentsDirectory
{
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
      NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
      return basePath;
}

//------------------------------------------------------------------------------

- (NSURL *)testFilePathURL
{
      return [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/test.caf",
                                     [self applicationDocumentsDirectory]]];
}

Please play the file after successfully saved. It works for me. check it out.

Please refer below link, I get more from here, Can I use AVAudioEngine to read from a file, process with an audio unit and write to a file, faster than real-time?

refer this sample project. It is what we are looking for https://github.com/VladimirKravchenko/AVAudioEngineOfflineRender


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...