Генерация тона с использованием DTMF и воспроизведение его с помощью AVAudioPlayer

Я хочу создать собственный тон DTMF и воспроизвести его на iPhone. Для этого я создал и выделил буфер памяти с настраиваемым тоном (ptr). Теперь я хочу создать объект NSData, инициализированный буфером памяти, и передать его в AVAudioPlayer, используя метод initWithData: error: instance.

Я написал следующий код, но когда я нажимаю кнопку «Играть», он вылетает.

#import "AudioPlayerViewController.h"
#include <stdlib.h>
#include <math.h>
#define SIZE 10
#define LENGTH 65535
const int PLAYBACKFREQ = 44100;
const float PI2 = 3.14159265359f * 2;
const int freq1 = 697;
const int freq2 = 1209;



@implementation AudioPlayerViewController

@synthesize playButton, stopButton;

- (void)viewDidLoad {
    [super viewDidLoad];
 // Allocate space for an array with ten elements of type int.
int *ptr = malloc(SIZE * sizeof(int));
if (ptr == NULL) NSLog(@"Error: Memory buffer could not be allocated.");
else NSLog(@"Allocation succeeded.");

 // The formula for the tone, the content of the buffer.
for(int i=0; i<SIZE; i++) ptr[i] = (sin(i*(PI2*(PLAYBACKFREQ/freq1))) + sin(i*    (PI2*(PLAYBACKFREQ/freq2)))) * 16383;
NSData *myData = [[NSData alloc] initWithBytesNoCopy:ptr length:SIZE];
free(ptr);
ptr = NULL;
audioPlayer = [[AVAudioPlayer alloc] initWithData:myData error:&error];
audioPlayer.numberOfLoops = -1;
}
-(IBAction) playAudio: (id) sender {
    if (audioPlayer == nil) NSLog([error description]);             
    else [audioPlayer play];
}
-(IBAction) stopAudio: (id) sender { [audioPlayer stop]; }

- (void)dealloc {
    [audioPlayer release];
    [myData release];
    [super dealloc];
}

@end

В документации описание метода initWithBytesNoCopy гласит:

Буфер, содержащий данные для нового объекта. байты должны указывать на блок памяти, выделенный с помощью malloc.

Итак, я уже сделал это, но это не работает.

Мы будем благодарны за любую помощь!


person Sagiftw    schedule 11.08.2010    source источник
comment
Вам нужно будет расширить его, это не сработает.   -  person Paul R    schedule 11.08.2010
comment
Все работает нормально, пока я не нажму кнопку Play, которая вызывает метод playAudio. Кнопка становится синей, и Xcode закрывает мое приложение.   -  person Sagiftw    schedule 11.08.2010
comment
Xcode не закрывает ваше приложение - вы, вероятно, каким-то образом вылетаете - что вам говорит работа под отладчиком?   -  person Paul R    schedule 11.08.2010
comment
Copyright 2004 Free Software Foundation, Inc. GDB - это бесплатное программное обеспечение, на которое распространяется Стандартная общественная лицензия GNU, и вы можете изменять его и / или распространять его копии при определенных условиях. Введите команду show copying, чтобы увидеть условия. На GDB нет никаких гарантий. Тип показать гарантию для подробностей. Этот GDB был настроен как i386-apple-darwin.sharedlibrary apply-load-rules all Присоединение к процессу 1993. 2010-08-11 13: 27: 58.053 gdb-i386-apple-darwin [1995: 613] _CFGetHostUUIDString: невозможно определить UUID для хоста. Ошибка: 35 (gdb)   -  person Sagiftw    schedule 11.08.2010
comment
Это совершенно бесполезно. Что Xcode предоставляет для трассировки стека? Что еще напечатано на консоли? На какой строке происходит сбой вашего приложения?   -  person Brad Larson    schedule 11.08.2010
comment
Кроме того, это точная копия вопроса, который вы только что задали: stackoverflow.com/questions/3456604/   -  person Brad Larson    schedule 11.08.2010
comment
Вы можете просто использовать это: github.com/danielgindi/DGToneGenerator   -  person daniel.gindi    schedule 19.10.2014


Ответы (1)


Вы создаете NSData без копирования данных, а затем освобождаете данные, поэтому теперь NSData имеет висящий указатель. Удалите строку free(ptr); и попробуйте снова. NSData освободит данные самостоятельно, когда с ними будет работать.

person Hollance    schedule 11.08.2010
comment
Второе, что вызывает подозрение, это то, что вы предоставляете AVAudioPlayer необработанные данные, и он, вероятно, не знает, как их интерпретировать. Аудиофайлы обычно имеют заголовок, который описывает частоту дискретизации, формат сэмплов и т. Д. Вы можете исправить это, добавив поддельный заголовок, например заголовок WAV, который довольно прост. Однако вам может потребоваться преобразовать ваши int в 16-битные значения. - person Hollance; 11.08.2010
comment
Вот демонстрационный проект, который показывает, как это сделать: github.com/hollance/AVBufferPlayer - person Hollance; 15.08.2010