iOS отключает все остальные кнопки при нажатии другой. Монофонический синтезатор басов с использованием avAudioPlayer

Я очень новичок в переполнении стека (это мой первый вопрос), но мне интересно, если вы, ребята, можете помочь.

Я сделал синтезатор басов, который работает, воспроизводя WAV. файлы с использованием avAudioPlayer, причем каждая заметка имеет свой собственный проигрыватель. Я разместил несколько кнопок на каждой ноте с разными пронумерованными тегами и использовал инструкцию switch, чтобы дать некоторый контроль над динамикой громкости. Существует также сегментированный контроллер, используемый для выбора из трех различных наборов образцов, используя выбор префикса к имени файла для URL. Проблема в том, что если вы пытаетесь нажать две кнопки, которые воспроизводят одну и ту же ноту и используют один и тот же avAudioPlayer, приложение вылетает.

Поскольку это басовый синтезатор, вы все равно ожидаете, что он будет монофоническим, если бы можно было нажать только одну кнопку за один раз, это могло бы решить мою проблему. Кто-нибудь знает, как бы я это сделал? Пожалуйста, используйте как можно более простые термины, так как я не очень знаком с кодированием. Я выложу код для одной заметки. (Есть 13 на одну октаву).

#import "AJCViewController.h"

@interface AJCViewController ()

@end

@implementation AJCViewController

NSString* bassPrefix;
NSURL *url;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
     bassPrefix = @"Z";
    // define default prefix for sample playback.

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.

}




   - (IBAction)c1Pressed:(UIButton *)sender {


         NSString *bass = [[NSString alloc] initWithFormat:@"%@C", bassPrefix];
         NSString *path = [[NSBundle mainBundle] pathForResource:bass ofType:@"wav"];
           [bass release];
           c1AudioPointer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL     fileURLWithPath:path] error:NULL];
           c1AudioPointer.delegate = self;
        // All buttons have tags, the buttons towards the top of the sceen having tag 0. The numbers buttons at the button 3. Switch statement varies volume based on where on the key it is pressed.
        switch (sender.tag)
        {

            case 0:
                [c1AudioPointer setVolume:0.4];
                break;

            case 1:
                [c1AudioPointer setVolume:0.5];
                break;

            case 2:
                [c1AudioPointer setVolume:0.6];
                break;

            case 3:
                [c1AudioPointer setVolume:0.8];
                break;

        }
        [c1AudioPointer play];
    }

    - (IBAction)c1Released:(UIButton *)sender {

        //While loop ramps down volume gradually to prevent clipping

        while (c1AudioPointer.volume > 0)
        {
            c1AudioPointer.volume = c1AudioPointer.volume - 0.1;
        }
        [c1AudioPointer stop];
        [c1AudioPointer release];


    }

    //De-allocate memory to free up audio buffer, necessary if note held till sample ends

    - (void)dealloc {

        [super dealloc];
        [c1AudioPointer release];
        [cSharp1AudioPointer release];
        [d1AudioPointer release];
        [dSharp1AudioPointer release];
        [e1AudioPointer release];
        [f1AudioPointer release];
        [fSharp1AudioPointer release];
        [g1AudioPointer release];
        [gSharp1AudioPointer release];
        [a1AudioPointer release];
        [bFlat1AudioPointer release];
        [b1AudioPointer release];
        [c2AudioPointer release];

    }



    - (IBAction)bassChoise:(UISegmentedControl *)sender {

        //Switch statement selects sample group based on state of segmented controller

        switch (self.bassChooserSegments.selectedSegmentIndex) {
            case 0:
                bassPrefix = @"Z";
                break;
            case 1:
                bassPrefix = @"Y";
                break;
            case 2:
                bassPrefix = @"X";
                break;
            default:
                break;
        }

    }
    @end

Спасибо за ваше время. Буду очень признателен за любую помощь или предложения о том, что я должен искать.

1 ответ

Если я правильно понимаю ваш вопрос, вы хотите играть на разных уровнях одной и той же ноты, и это приводит к сбою приложения?

Я бы предположил, что причиной сбоя является то, что вы отпускаете указатель дважды, где основная причина заключается в том, что вы начинаете игру на одном уровне, а затем начинаете игру на другом уровне, что приводит к утечке памяти первого игрока.

Вы, вероятно, не хотите перераспределять его, просто меняя уровень на лету. Вы теряете память, если не выпускаете первыми в любом случае.

Вы можете добавить тест, чтобы увидеть, играет ли нота, и только изменить громкость.

- (IBAction)c1Pressed:(UIButton *)sender {
  BOOL isPlaying = YES;
  if (nil == c1AudioPointer) {  // Don't create new avaudioplayer if only changing the volume of currently playing note.
     isPlaying = NO;
     NSString *bass = [[NSString alloc] initWithFormat:@"%@C", bassPrefix];
     NSString *path = [[NSBundle mainBundle] pathForResource:bass ofType:@"wav"];
     [bass release];
     c1AudioPointer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL     fileURLWithPath:path] error:NULL];
     c1AudioPointer.delegate = self;
  }
  // All buttons have tags, the buttons towards the top of the sceen having tag 0. The numbers buttons at the button 3. Switch statement varies volume based on where on the key it is pressed.
        switch (sender.tag)
        {

            case 0:
                [c1AudioPointer setVolume:0.4];
                break;

            case 1:
                [c1AudioPointer setVolume:0.5];
                break;

            case 2:
                [c1AudioPointer setVolume:0.6];
                break;

            case 3:
                [c1AudioPointer setVolume:0.8];
                break;

        }
        if (!isPlaying) {
          [c1AudioPointer play];
        }
    }

Если вы хотите снова сыграть ноту, когда проводите пальцем по разным уровням, сначала освободите ее.

Кстати. почему вы не используете ARC? Вы не столкнетесь с этой проблемой.

Другие вопросы по тегам