I am using the apple example code SpleakHere. in this code there is a calss called AQRecorder, it is a C class. i want to send the sound bytes to an objective-c object i have. this object send the dat over udp. here is the function in which im trying to perform an objective-c function inside the c code.
void AQRecorder::MyInputBufferHandler( void * inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inBuffer,
const AudioTimeStamp * inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription* inPacketDesc)
{
AQRecorder *aqr = (AQRecorder *)inUserData;
try {
if (inNumPackets > 0) {
// write packets to file
XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize,
inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData),
"AudioFileWritePackets failed");
aqr->mRecordPacket += inNumPackets;
NSData* data=[NSData dataWithBytes:inBuffer->mAudioData length:inBuffer->mAudioDataByteSize];
[(Udp*)udpp sendData:data];
}
// if we're not stopping, re-enqueue the buffe so that it gets filled again
if (aqr->IsRunning())
XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
} catch (CAXException e) {
char buf[256];
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}
although the NSData functions works fine, i am not able to ad my object (Udp) to the class and therefore cant call its functions. i tried declaring the Udp object everywhere (inside class,outside class,header .mm file ,as void*...) but nothing would compile...
though i wan't able to add an object in order to send the data... i used NSNptification instead in order to port the data from the c object to the objective-c object.
help please
though i wan't able to add an object in order to send the data... i used NSNotification instead in order to port the data from the c object to the objective-c object
Try changing the extension of all .m files to .mm.
If that works, then you have a dependency issue. If an Objective-C file includes a C++ file, then the extension of that Obj-C file should be .mm instead of .m. Moreover, if this Objective-C file now gets included in some other Objective-C file, then the extension of that file should be .mm as well.
Check file type. Select "Objective C++ preprocessed".
You can make in File inspector window on the right panel for XCode4
or
"Get info" in file context menu for older XCode versions.
Related
I'm trying to write a password encryption function into my app, following this article.
I wrote a function that runs the CCCalibratePBKDF function and outputs the number of rounds.
const uint32_t oneSecond = 1000;
uint rounds = CCCalibratePBKDF(kCCPBKDF2,
predictedPasswordLength,
predictedSaltLength,
kCCPRFHmacAlgSHA256,
kCCKeySizeAES128,
oneSecond);
This works perfectly, but when I try to implement the next part it all goes wrong.
I can start writing the CCKeyDerivationPBKDF function call and it auto-completes the function and all the parameters. As I go through filling it in all the parameters are also auto-completed.
- (NSData *)authenticationDataForPassword: (NSString *)password salt: (NSData *)salt rounds: (uint) rounds
{
const NSString *plainData = #"Fuzzy Aliens";
uint8_t key[kCCKeySizeAES128] = {0};
int keyDerivationResult = CCKeyDerivationPBKDF(kCCPBKDF2,
[password UTF8String],
[password lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
[salt bytes],
[salt length],
kCCPRFHmacAlgSHA256,
rounds,
key,
kCCKeySizeAES128);
if (keyDerivationResult == kCCParamError) {
//you shouldn't get here with the parameters as above
return nil;
}
uint8_t hmac[CC_SHA256_DIGEST_LENGTH] = {0};
CCHmac(kCCHmacAlgSHA256,
key,
kCCKeySizeAES128,
[plainData UTF8String],
[plainData lengthOfBytesUsingEncoding: NSUTF8StringEncoding],
hmac);
NSData *hmacData = [NSData dataWithBytes: hmac length: CC_SHA256_DIGEST_LENGTH];
return hmacData;
}
But as soon as I hit ; it marks an error saying "No matching function for call to 'CCKeyDerivationPBKDF'" and it won't build or anything.
I've imported CommonCrypto/CommonKeyDerivation.h and CommonCrypto/CommonCryptor.h as both of these were necessary for the enum names.
First, make sure that you haven't done anything funny with your include path (in particular, I do not recommend #HachiEthan's solution, which just confuses things). In general, leave this alone, and specifically don't add things like /usr/include to it. Make sure you've added Security.framework to your link step. This is the usual cause of problems.
The biggest thing you want to be sure of is that you're getting the iOS 5 Security.framework (rather than some other version like the OS X 10.6 or iOS 4 versions). But my suspicion is that you have a problem with your build settings.
If you want to see a framework that does all of this for reference, take a look at RNCryptor.
Right, I've found the problem (and solution).
Because I was using ZXing I had to rename the .m file to .mm so it could run the C++ stuff in the ZXing library.
I don't know why but renaming the file this way broke the CCKeyDerivationPBKDF function.
I've now moved the crypto code into it's own class and left it as .m and all I need now is to include the two imports as I did in the original post.
I didn't have to include any frameworks or anything.
I'm writing a program using the C language with gtk+ and gtksourceview-2.0.
I'm using a GtkFileChooser for the user to choose a file and when he clicks on it, i want the content to be loaded to the GtkSourceView' TextBuffer
this is the function that gets executed when a user double click's a file on the GtkFileChooser:
void on_file_activated(GtkWidget *widget, gpointer data) {
GFile *file;
FILE *fp;
gchar *path_name;
long file_size;
gchararray file_buffer;
file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
path_name=g_file_get_path(file);
g_debug("%s is chosen\n", path_name);
fp=fopen(path_name, "r");
g_assert( fp != NULL);
fseek(fp, 0L, SEEK_END);
file_size = ftell(fp);
rewind(fp);
g_debug("file size: %ld\n",file_size*sizeof(gchar));
file_buffer=calloc(file_size, sizeof(gchar));
g_assert(file_buffer != NULL);
fread(&file_buffer,file_size,1,fp);
g_debug("after fread");
//file_buffer[file_size*sizeof(gchar)]=0;
//g_debug("after adding zero: %s",file_buffer);
gtk_text_buffer_set_text (textbuffer, file_buffer,2);
g_debug("after set text");
g_object_unref(file);
}
this is the output of my application:
** (tour_de_gtk:18107): DEBUG: /home/ufk/Projects/gtk-projects/tour-de-gtk/Debug/src/examples/example_gtk_label/main.c is chosen
** (tour_de_gtk:18107): DEBUG: file size: 16
** (tour_de_gtk:18107): DEBUG: after fread
after then i get a segmentation fault on the command gtk_text_buffer_set_text
as you can see i have two commands that are commented out. trying to g_debug the buffer which obviously creates a segmentation fault because i didn't add a zero to the end of the string, and even when I try to add zero to the end of the string i get a segmentation fault. I probably did something wrong.
here i'm trying to write only the first two characters of the buffer but with no luck.
any ideas?
update
the finished function:
void on_file_activated(GtkWidget *widget, gpointer data) {
GFile *file;
gchar *path_name;
long file_size;
gchar *file_buffer;
GError *error;
gboolean read_file_status;
file = gtk_file_chooser_get_file(GTK_FILE_CHOOSER(widget));
path_name=g_file_get_path(file);
g_debug("%s is chosen\n", path_name);
read_file_status=g_file_get_contents (path_name,&file_buffer,NULL, &error);
if (read_file_status == FALSE) {
g_error("error opening file: %s\n",error && error->message ? error->message : "No Detail");
return;
}
gtk_text_buffer_set_text (textbuffer, file_buffer,-1);
g_debug("after set text");
g_object_unref(file);
}
There are a lot of improvements possible here, you may already know many and just be messing around, but I'll list several in case.
gchararray file_buffer;
Just use char*
g_assert( fp != NULL);
Should use assert for programming errors, not runtime errors, so here g_printerr() or a dialog would be better
fseek(fp, 0L, SEEK_END);
file_size = ftell(fp);
rewind(fp);
fstat(fileno(fp), &statbuf) is probably a better way to do this, but the whole approach is kind of bad; rather than get the size, it's better to just read into a dynamically-growing buffer. Or if you're willing to preallocate the whole buffer, just use g_file_get_contents(). Another approach is g_file_query_info() (which is more portable and uses the vfs)
file_buffer=calloc(file_size, sizeof(gchar));
g_new0(char, file_size) is nicer, or g_malloc0(file_size). Also you need file_size+1 to make room for the nul byte.
fread(&file_buffer,file_size,1,fp);
Here you want file_buffer (a char*) rather than &file_buffer (a char**). This is probably the actual cause of the immediate breakage.
You also need to check the return value of fread().
Also missing here is g_utf8_validate() on the data read in.
Have a look at the implementation of g_file_get_contents() to see one approach here. You could also use g_file_load_contents to use a GFile instead of a path (portable, uses vfs) or better yet in a real-world app, g_file_load_contents_async().
To debug segfaults, the two best tools are:
run in gdb, wait for crash, then type "bt"; be sure to use -g with your compiler when you compile
run in valgrind, see where it says you look at bad memory
I am coding an audio app for the iphone where I need to use some C code to deal with the audio files. In short, I have a memory leak that is causing the app to crash after so many files have been loaded. The problem is related to a Struct that I create that holds the audio files when read in. The Struct is created as follows;
typedef struct {
UInt32 frameCount; // the total number of frames in the audio data
UInt32 sampleNumber; // the next audio sample to play
BOOL isStereo; // set to true if there is data audioDataRight member
AudioUnitSampleType *audioDataLeft; // complete left channel of audio data read from file
AudioUnitSampleType *audioDataRight; // complete right channel of audio data read file
} soundStruct, *soundStructPtr;
The Struct is then Initialized in the header like this;
soundStruct phraseSynthStructArray[3];
I then attempt to join two files that have been read into phraseSynthStructArray[phrase1Index] and phraseSynthStructArray[phrase2Index] and put the combined file into phraseSynthStructArray[synthPhraseIndex] like this;
- (BOOL) joinPhrases:(UInt32)phrase1Index phrase2Index:(UInt32)phrase2Index synthPhraseIndex:(UInt32)synthPhraseIndex{
// get the combined frame count
UInt64 totalFramesInFile = inArray[phrase1Index].frameCount + inArray[phrase2Index].frameCount;
//now resize the synthPhrase slot buffer to be the same size as both files combined
// phraseOut is used to hold the combined data prior to it being passed into the soundStructArray slot
free(phraseSynthStructArray[synthPhraseIndex].audioDataLeft);
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = NULL;
phraseSynthStructArray[synthPhraseIndex].frameCount = 0;
phraseSynthStructArray[synthPhraseIndex].frameCount = totalFramesInFile;
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType));
for (UInt32 frameNumber = 0; frameNumber < inArray[phrase1Index].frameCount; ++frameNumber) {
phraseSynthStructArray[synthPhraseIndex].audioDataLeft[frameNumber] = phraseSynthStructArray[phrase1Index].audioDataLeft[frameNumber];
}
UInt32 sampleNumber=0;
for (UInt32 frameNumber = phraseSynthStructArray[phrase1Index].frameCount; frameNumber < totalFramesInFile; ++frameNumber) {
phraseSynthStructArray[synthPhraseIndex].audioDataLeft[frameNumber] = phraseSynthStructArray[phrase2Index].audioDataLeft[sampleNumber];
sampleNumber++;
}
return YES;
}
This all works fine and the resulting file is joined and can be used. The isuue I am having is when I allocate the memory here, phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType)); then next time the method is called, this memory leaks each time and eventually crashes the app. The reason I need to allocate the memory here is because the memory has to be resized to accomodate the joined file which varies in length depending on the size of the input files.
I cannot free the memory after the operation as its needed elsewhere after the method has been called and I have tried to free it before (in joinPhrases method above), but this does not seem to work. I have also tried using realloc to free/reallocate the memory by passing the pointer to the previously allocated memory but this casues a crash stating EXEC_BAD_ACCESS.
I am not a seasoned C programmer and Cannot figure out what I am doing wrong here to cause the leak. I would appreciate some advice to help me track down this issue as I have been banging my head against this for days with no joy. I have read thats its a bad idea to have Pointers in Structs, could this be the root of my problem?
Thanks in advance,
K.
Maybe this helps:
- (BOOL) joinPhrases:(UInt32)phrase1Index phrase2Index:(UInt32)phrase2Index synthPhraseIndex:(UInt32)synthPhraseIndex{
// get the combined frame count
UInt64 totalFramesInFile = inArray[phrase1Index].frameCount + inArray[phrase2Index].frameCount;
. . .
void* old_ptr = phraseSynthStructArray[synthPhraseIndex].audioDataLeft;
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType));
if( old_ptr ) free(old_ptr);
. . .
return YES;
}
And make sure that there is no garbage in phraseSynthStructArray[synthPhraseIndex]
I'm building an iPhone Application that records sound. I make use of Audio Queue Services, and everything works great for the recording.
The thing is, I'm using AudioFileWritePackets for file writing, and I'm trying to put the same "AAC + ADTS" packets to a network socket.
The resulting file is different since some "headers" or "adts header" might be missing. I am searching for ideas on how to write the ADTS header and/or AAC header? Could the community assist me with this or refer me to a guide that demonstrated how to do this?
I currently have my Buffer Handler method:
void Recorder::MyInputBufferHandler(void inUserData,
AudioQueueRefinAQ, AudioQueueBufferRefinBuffer,
const AudioTimeStamp*inStartTime,
UInt32 inNumPackets,
const AudioStreamPacketDescription*inPacketDesc) {
AQRecorder *aqr = (AQRecorder *)inUserData;
try {
if (inNumPackets > 0) {
// write packets to file
XThrowIfError(AudioFileWritePackets(aqr->mRecordFile,
FALSE,
inBuffer->mAudioDataByteSize,
inPacketDesc,
aqr->mRecordPacket,
&inNumPackets,
inBuffer->mAudioData),
"AudioFileWritePackets failed");
fprintf(stderr, "Writing.");
// We write the Net Buffer.
[aqr->socket_if writeData :(void *)(inBuffer->mAudioData)
:inBuffer->mAudioDataByteSize];
aqr->mRecordPacket += inNumPackets;
}
// if we're not stopping, re-enqueue the buffe so that it gets filled again
if (aqr->IsRunning()) {
XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL),
"AudioQueueEnqueueBuffer failed");
}
}
catch (CAXException e) {
char buf[256];
fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
}
}
I've found the solution for this:
I implemented the callback
XThrowIfError(
AudioFileInitializeWithCallbacks(
this,
nil,
BufferFilled_callback,
nil,
nil,
//kAudioFileCAFType,
kAudioFileAAC_ADTSType,
&mRecordFormat,
kAudioFileFlags_EraseFile,
&mRecordFile),
"InitializeWithCallbacks failed");
... And voilá! The real callback you have to implement is BufferFilled_callback. Here is my implementation:
OSStatus AQRecorder::BufferFilled_callback(
void * inUserData,
SInt64 inPosition,
UInt32 requestCount,
const void * buffer,
UInt32 * actualCount) {
AQRecorder *aqr = (AQRecorder *)inUserData;
// You can write these bytes to anywhere.
// You can build a streaming server
return 0;
}
If you want to see more about audio queue services, you can get some ideas from Flipzu for iPhone (ex-app for live broadcasting audio // we have to shut it down because we could not raise money).
https://github.com/lucaslain/Flipzu_iPhone
Best,
Lucas.
I've recently encountered this issue with the iLBC codec, and arrived at the solution as follows:
Record the audio data you want and just write it to a file. Then, take that file and do an octal dump on it. You can use the -c flag to see ascii characters.
Then, create a separate file that you know doesn't contain the header. This is just your data from the buffers on the audio queue. Octal dump that, and compare.
From this, you should have the header and enough info on how to proceed. Hope this helps.
Has someone been able to make
http://www.surina.net/soundtouch/
work for iPhone?
Simple Xcode Demo would be helpful.
I'd just like to play a soundeffect with some pitch manipulation.
thx
chris
The best way to implement audio effects using SoundTouch is using also SoundStretch.
You can download the source code of both from here http://www.surina.net/soundtouch/sourcecode.html
SoundStretch is a command-line program that performs SoundTouch
library effects on WAV audio files. The program is a source code
example how SoundTouch library routines can be used to process sound
in other programs, but it can be used as a stand-alone audio
processing tool as well.
SoundStretch features:
Reads & writes .wav audio files
Allows very broad parameter adjustment ranges:
Tempo & Playback Rate adjustable in range -95% .. +5000%
The sound Pitch (key) adjustable in range -60 .. +60 semitones (+- 5 octaves).
Beats-Per-Second (BPM) detection that can adjust tempo to match with the desired BPM rate.
Full source codes available
Command-line interface allows using the SoundStretch utility for processing .wav audio files in batch mode
Supports processing .wav audio streams through standard input/output pipes
SoundStretch uses the SoundTouch library routines for the audio procesing.
Example of use:
NSArray *effects = [NSArray arrayWithObjects:#"-rate=-22", nil];
NSURL *audio = [self base:input output:output effects:effects];
Where base:output:effects is defined as:
- (NSURL *)base:(NSURL *)input output:(NSURL *)output effects:(NSArray *)effects{
int _argc = 3 + (int)[effects count];
const char *_argv[]={"createWavWithEffect",[[input path] UTF8String], [[output path] UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String],[#"" UTF8String]};
for (int i=0; i<[effects count]; i++) {
_argv[i+3] = [effects[i] UTF8String];
}
createWavWithEffect(_argc, _argv);
// IMPORTANT! Check the file size, maybe you will need to set by yourself
return output;
}
If you don't want to compile by yourself SoundTouch, I have shared a GitHub repository with that libraries compiled for armv7, armv7s, arm64, i386 and x86_64
https://github.com/enrimr/soundtouch-ios-library
And if you want to use SoundTouch by yourself without using SoundStretch, you have to add SoundTouch directory (which includes libSoundTouch.a and the directory with headers) in your Xcode project.
For SWIFT projects:
Programming with SWIFT you can't import a .h so you will need to create a .h file named <Your-Project-Name>-Bridging-Header-File.h
Then reference it in your projects build settings (under "Swift Compiler" look for "Objective C Bridging Header") with:
$(SRCROOT)/<Your-Project-Name>-Bridging-Header.h
And now you must be able to use SoundTouch class.
For Objective-C projects:
Include the following line
#include "SoundTouch.h"
in your controller file.
Implementation of createWavWithEffect:
int createWavWithEffect(const int nParams, const char * const paramStr[])
{
WavInFile *inFile;
WavOutFile *outFile;
RunParameters *params;
SoundTouch soundTouch;
fprintf(stderr, _helloText, SoundTouch::getVersionString());
try
{
// Parse command line parameters
params = new RunParameters(nParams, paramStr);
// Open input & output files
openFiles(&inFile, &outFile, params);
if (params->detectBPM == TRUE)
{
// detect sound BPM (and adjust processing parameters
// accordingly if necessary)
detectBPM(inFile, params);
}
// Setup the 'SoundTouch' object for processing the sound
setup(&soundTouch, inFile, params);
// clock_t cs = clock(); // for benchmarking processing duration
// Process the sound
process(&soundTouch, inFile, outFile);
// clock_t ce = clock(); // for benchmarking processing duration
// printf("duration: %lf\n", (double)(ce-cs)/CLOCKS_PER_SEC);
// Close WAV file handles & dispose of the objects
delete inFile;
delete outFile;
delete params;
fprintf(stderr, "Done!\n");
}
catch (const runtime_error &e)
{
// An exception occurred during processing, display an error message
fprintf(stderr, "%s\n", e.what());
return -1;
}
return 0;
}