Converting Objective C to C Matrix Manipulation - objective-c

Okay, so I had working code written in all objective c (yes, I know that objc is technically just C. But i mean I had it written with messages and stuff. I only have a java background and do not know much about plain old C) but it ran incredibly slow. So I wrote out (what i thought) was the same code, but now this set of loops produces different values (for only some of the numbers) and I cannot, for the life of me, figure out whats different. What I am doing is looping 10 times and doing 1 multiplication and 1 addition between matricies. I'm hoping someone with more background with the two languages can pick out the part of code that I transcribed incorrectly. I did not change anything beforehand for any of the arrays (those were hardcoded in and uneffected) so A1, A2, etc have the same values in both parts of code.
Current code in C:
for (int m = 0; m < 10; m++) {
//Do matrix multiplication between A1 and A2. Store in temporary B1
for( int i = 0; i < 13; i++ )
for( int j = 0; j < 43; j++ ) {
double tempTotal = 0;
for( int k = 0; k < 43; k++){
tempTotal = tempTotal + A1[i][k] * A2[k][j];
}
B1[i][j] = tempTotal;
}
//Assign B1 data back into A1 after the multiplication is finished
for(int i = 0; i < 13; i++)
for(int j = 0; j<43; j++)
A1[i][j] = B1[i][j];
//Add C1 and A1. Store into C1.
for (int l = 0; l < 13; l++)
for (int n = 0; n < 43; n++)
C1[l][n] = C1[l][n] + A1[l][n];
}//end m for loop
This was the old Obj c code:
for (int m = 0; m < 10; m++) {
//multiply A1 and A2. Store into A1
A1 = [LCA_Computation multiply:A1 withArray:A2]; //LCA_Computation is the name of the .m class file in which this all happens.
//Add C1 and A1. Store into C1
for (int i = 0; i < 13; i++)
for (int j = 0; j < 43; j++)
[[C1 objectAtIndex:i] replaceObjectAtIndex:j withObject:[NSNumber numberWithDouble: [[[C1 objectAtIndex: i] objectAtIndex: j] doubleValue] + [[[A1 objectAtIndex: i] objectAtIndex: j] doubleValue]]];
}//end m for loop
//multiply method
+ (NSMutableArray*)multiply:(NSMutableArray*)a1 withArray:(NSMutableArray*)a2
{
int a1_rowNum = [a1 count];
int a2_rowNum = [a2 count];
int a2_colNum = [[a2 objectAtIndex:0] count];
NSMutableArray *result = [NSMutableArray arrayWithCapacity:a1_rowNum];
for (int i = 0; i < a1_rowNum; i++) {
NSMutableArray *tempRow = [NSMutableArray arrayWithCapacity:a2_colNum];
for (int j = 0; j < a2_colNum; j++) {
double tempTotal = 0;
for (int k = 0; k < a2_rowNum; k++) {
double temp1 = [[[a1 objectAtIndex:i] objectAtIndex:k] doubleValue];
double temp2 = [[[a2 objectAtIndex:k] objectAtIndex:j] doubleValue];
tempTotal += temp1 * temp2;
}
//the String format is intentional. I convert them all to strings later. I just put it in the method here where as it is done later in the C code
[tempRow addObject:[NSString stringWithFormat:#"%f",tempTotal]];
}
[result addObject:tempRow];
}
return result;
}

This issue had to do with prior memory management issues causing 0's to be used in some calculations.

Related

Finding consecutive integers in an Array

I am looking for an algorithm to determine if there are at least three consecutive numbers in an array. I have found several and tweaked them a bit, but it does not seem to be working. Below is what I am currently doing. The array is sorted using an NSSortDescriptor prior to the loop.
For example:
in an array [5,6,101,102,103] the three consecutive numbers are [101,102,103]
and the below function should return YES.
int c = [checkArray count];
int a,b = 0;
int cnt = 1;
for (int i = 1; i < c; i++)
{
a = [[checkArray objectAtIndex:i] intValue];
b = [[checkArray objectAtIndex:i-1] intValue] - 1;
if (a == b)
{
cnt++;
if (cnt == 3)
return YES;
} else {
cnt = 1;
}
}
return NO;
This is an alternative approach. I haven't tested it, but you should get the idea.
int c = [checkArray count];
int a,b,c = 0;
a = [[checkArray objectAtIndex:0] intValue];
b = [[checkArray objectAtIndex:1] intValue];
for (int i = 2; i < c; i++)
{
c = [[checkArray objectAtIndex:i] intValue];
if (a+2 == b+1 && b+1 == c)
return YES;
a = b;
b = c;
}
return NO;
It has the additional advantage of being easily optimized.
You should be able to do something like...
for (int i = 1; i < checkArray.count-1; i++)
{
int lower = [checkArray[i-1] intValue] +1;
int mid = [checkArray[i] intValue];
int upper = [checkArray[i+1] intValue] -1;
if (lower == mid && mid == upper) {
return YES;
}
}
return NO;
You only need to check each number once. No need to count anything. Each number you check is the middle of three numbers. If the one before and the one after are one less and one greater respectively then the three numbers are consecutive.

Accelerate Framework FFT to create audio fingerprint in iOS

First of all, sorry for my bad English.
I just started with the Objective-C a couple of week ago. I'm doing a project that require me to compared two audio signals recorded from two iOS devices. So far, I managed to record two .aif files from an iPhone 4s and iPhone 4. Then I try to apply the following algorithm A Highly Robust Audio Fingerprinting System. by: Jaap Haitsma" to get two fingerprints (in binary bit patterns 101011010) and then compare them with each other bits by bits. But so far, the result I got is somewhere between 45% and 55% which is pretty much the random probability between 0s and 1s. So can somebody give me any advice. Here's the code so far:
CalculateFingerprint *myCalculateFingerprint = [CalculateFingerprint alloc];
SInt16 *inputBuffer;
path4 = [documentsDirectory stringByAppendingPathComponent:fileName4];
/////////Calculate for the 4 file
fileURL = [NSURL fileURLWithPath:path4];
status = AudioFileOpenURL((__bridge CFURLRef)fileURL, kAudioFileReadPermission,kAudioFileAIFFType, &myAudioFile);
status = AudioFileGetPropertyInfo(myAudioFile,
kAudioFilePropertyAudioDataPacketCount,
&propertySizeDataPacketCount,
&writabilityDataPacketCount);
status = AudioFileGetProperty(myAudioFile,
kAudioFilePropertyAudioDataPacketCount,
&propertySizeDataPacketCount,
&numberOfPackets);
status = AudioFileGetPropertyInfo (myAudioFile,
kAudioFilePropertyMaximumPacketSize,
&propertySizeMaxPacketSize,
&writabilityMaxPacketSize);
status = AudioFileGetProperty(myAudioFile,
kAudioFilePropertyMaximumPacketSize,
&propertySizeMaxPacketSize,
&maxPacketSize);
inputBuffer = (SInt16 *)malloc(numberOfPackets * maxPacketSize);
currentPacket = 0;
status = AudioFileReadPackets(myAudioFile,
false, &numberOfBytesRead,
NULL,
currentPacket,
&numberOfPackets,
inputBuffer);
[myCalculateFingerprint calculateFingerprint:inputBuffer sampleCount:numberOfPackets index:indexFile];
status = AudioFileClose(myAudioFile);
Here's the calculation of fingerprint code:
-(void)calculateFingerprint :(SInt16*)samples
sampleCount:(int)sampleCount
index:(int)indexFile{
//Divide the audio signal into 32 frames
frames myFrames [32];
int stepFrames = sampleCount / 62;
int number = 0;
int index ;
for (int i = 0; i < 32; ++i){
index = 0;
myFrames[i].start = number;
myFrames[i].end = number + (32*stepFrames);
myFrames[i].dataFrames = (SInt16*)malloc((myFrames[i].end -number+1)*sizeof(SInt16));
for (int j = number;j<=myFrames[i].end; ++j){
myFrames[i].dataFrames[index] = samples[j];
++index;
}
number = number + stepFrames;
}
//Calculate FFT for each of the audio signal frames.
CalculateFFT *myCalculateFFT = [[CalculateFFT alloc] init];
theFFT myFFTData [32];
for (int i = 0; i <32; ++i){
myFFTData[i].FFTdata = [myCalculateFFT calculateFFTForData:myFrames[i].dataFrames];
}
//each index represent the frequency as followed:
// index i is frequency i * 44100/1024
//We only need 33 bands from 300 Hz to 2000Hz, so we will get the FFTdata from the index 7 to 40
float energy [33][33];
for (int i =0; i < 33; ++i){
energy[0][i] = 0;
}
int stepBand;
for (int i = 1; i < 33; ++i){
for (int j = 0; j < 33; ++j){
energy[i][j] = myFFTData[i].FFTdata[j+7];
}
}
//next we calculate the bits for the audio fingerprint
Float32 check = 0;
int fingerPrint [32][32];
NSMutableString *result = [[NSMutableString alloc]init];
for (int i = 0; i < 32; ++i){
for (int j = 0; j <32; ++j){
check = energy[i+1][j] -energy[i+1][j+1] -energy[i][j] +energy[i][j+1];
if (check > 0){
fingerPrint[i][j] = 1;//[tempBitFingerPrint addObject:[NSNumber numberWithInt:1]];
}else {
fingerPrint[i][j] = 0;//[tempBitFingerPrint addObject:[NSNumber numberWithInt:0]];
}
[result appendString:[NSString stringWithFormat:#"%d",fingerPrint[i][j]]];
}
}
And finally the FFT calculation code:
-(void)FFTSetup{
UInt32 maxFrames = 1024;
originalReal = (float*) malloc(maxFrames*sizeof(float));
originalRealTransfer = (float*)malloc(maxFrames*sizeof(float));
obtainedReal = (float*) malloc(maxFrames *sizeof(float));
freqArray = (Float32*) malloc((maxFrames/2) *sizeof(Float32));
fftLog2n = log2f(maxFrames);
fftN = 1 << fftLog2n;
fftNOver2 = maxFrames/2;
fftBufferCapacity = maxFrames;
fftIndex = 0;
fftA.realp = (float*)malloc(fftNOver2*sizeof(float));
fftA.imagp = (float*)malloc(fftNOver2*sizeof(float));
fftSetup = vDSP_create_fftsetup(fftLog2n,FFT_RADIX2);
}
-(Float32*) calculateFFTForData:(SInt16*)sampleData
{
[self FFTSetup];
int stride = 1;
for (int i = 0; i < fftN; ++i){
originalReal[i] = (float) sampleData[i];
}
UInt32 maxFrames = 1024;
//Apply Hann window on the data
int windowSize = maxFrames;
float * window = (float*)malloc(sizeof(float)*windowSize);
memset(window, 0, sizeof(float)*windowSize);
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM);
vDSP_vmul(originalReal,1,window,1,originalRealTransfer,1,windowSize);
vDSP_ctoz((COMPLEX*) originalRealTransfer,2,&fftA,1,fftNOver2);
vDSP_fft_zrip(fftSetup,&fftA, stride,fftLog2n,FFT_FORWARD);
float scale = (float) 1.0 /(2*fftN);
vDSP_vsmul(fftA.realp,1,&scale,fftA.realp,1,fftNOver2);
vDSP_vsmul(fftA.imagp,1,&scale,fftA.imagp,1,fftNOver2);
vDSP_ztoc(&fftA,1,(COMPLEX*)obtainedReal,2,fftNOver2);
int index = 0;
NSMutableString *testResult = [[NSMutableString alloc]init];
for (int i = 0; i < fftN; i=i+2){
freqArray[index] = (obtainedReal[i]*obtainedReal[i])+(obtainedReal[i+1]*obtainedReal[i+1]);
[testResult appendString:[NSString stringWithFormat:#"%f ",freqArray[index]]];
++index;
}
return freqArray;
}

Program Crash - probably a memory retain misuse

I have an array of Objective-C objects that is to be sorted on a field of the object. I use a simple selection sort since the array is small. The sort works and the correct data is in the array, but after adding about 3 or 4 objects to the array and resorting each time it crashes.
Any help would be appreciated. The error is EXC_BAD_ACCESS Thanks in advance. The code follows:
TopTenDataClass *temp1 = [[TopTenDataClass alloc] init];
TopTenDataClass *temp2 = [[TopTenDataClass alloc] init];
for (int i = 0; i < [topTenDataArray count]; i++)
{
int minIndex = i;
for (int j = i; j < [topTenDataArray count]; j++)
{
temp1 = [topTenDataArray objectAtIndex:minIndex];
temp2 = [topTenDataArray objectAtIndex:j];
if ( temp2.timeInSeconds < temp1.timeInSeconds)
minIndex = j;
}
[topTenDataArray exchangeObjectAtIndex:minIndex withObjectAtIndex:i];
}
[temp2 release]; [temp1 release];
The issue is that inside of your loop you are changing the values of temp1 and temp2. When you release them after the loop completes, you are not releasing the objects that you created before the loop started. Instead you are attempting to release some other object that you did not alloc/init (in this part of the code). Probably that is what is causing your crash.
I'd suggest trying something like:
TopTenDataClass *temp1 = nil;
TopTenDataClass *temp2 = nil;
for (int i = 0; i < [topTenDataArray count]; i++)
{
int minIndex = i;
for (int j = i; j < [topTenDataArray count]; j++)
{
temp1 = [topTenDataArray objectAtIndex:minIndex];
temp2 = [topTenDataArray objectAtIndex:j];
if ( temp2.timeInSeconds < temp1.timeInSeconds)
minIndex = j;
}
[topTenDataArray exchangeObjectAtIndex:minIndex withObjectAtIndex:i];
}
You don't need to assign a new object instance to temp1 and temp2 before the loop, because you just overwrite their values inside your loop.
Do also note that if topTenDataArray has only a single element in it your code will call [topTenDataArray exchangeObjectAtIndex:0 withObjectAtIndex:0], which may also be a problem (the API docs don't say that you can't exchange an object with itself, but they don't say that you can, either).

Randomly select x amount of items in a "list"

I would like to select x amount of items randomly from a "list" in objective C store them in an other "list" (each item can only be selected one) , I'm talking about lists because I'm coming from Python. What would be the best way to store a list of strings in Objective C ?
cheers,
You should use NSMutableArray class for changeable arrays or NSArray for non-changeable ones.
UPDATE: a piece of code for selecting a number of items from an array randomly:
NSMutableArray *sourceArray = [NSMutableArray array];
NSMutableArray *newArray = [NSMutableArray array];
int sourceCount = 10;
//fill sourceArray with some elements
for(int i = 0; i < sourceCount; i++) {
[sourceArray addObject:[NSString stringWithFormat:#"Element %d", i+1]];
}
//and the magic begins here :)
int newArrayCount = 5;
NSMutableIndexSet *randomIndexes = [NSMutableIndexSet indexSet]; //to trace new random indexes
for (int i = 0; i < newArrayCount; i++) {
int newRandomIndex = arc4random() % sourceCount;
int j = 0; //use j in order to not rich infinite cycle
//tracing that all new indeces are unique
while ([randomIndexes containsIndex:newRandomIndex] || j >= newArrayCount) {
newRandomIndex = arc4random() % sourceCount;
j++;
}
if (j >= newArrayCount) {
break;
}
[randomIndexes addIndex:newRandomIndex];
[newArray addObject:[sourceArray objectAtIndex:newRandomIndex]];
}
NSLog(#"OLD: %#", sourceArray);
NSLog(#"NEW: %#", newArray);

Selecting random numbers iphone sdk

I want to select 10 random numbers from 1 to 35.
I am trying to do the following, but I get some repeated numbers
int totalNumberCnt = 1;
while (totalNumberCnt < 11) {
int randomNumber1 = 1 + arc4random() % 35;
NSString *numberString = [NSString stringWithFormat: #"%d",randomNumber1];
NSLog(numberString);
[firstNumber addObject:numberString];
[secondNumber addObject:numberString];
totalNumberCnt++;
}
Thank you for your help.
Repeated numbers are to be expected; it is random after all, and any random sample will contain repeats.
int unique = 0;
int numbers[35];
for (int i = 0; i < 35; i++) {
numbers[i] = 0;
}
while (unique < 10) {
int x = arc4random() % 35;
if (numbers[x] == 0) {
numbers[x] = 1;
++unique;
}
}
for (int i = 0; i < 35; i++) {
if (numbers[i] == 1) {
NSString *str = [NSString stringWithFormat: #"%d", i];
NSLog(#"%#", str);
}
}