superpoweredSDK / Low-Latency-Android-iOS-Linux-Windows-tvOS-macOS-Interactive-Audio-Platform

🇸Superpowered Audio, Networking and Cryptographics SDKs. High performance and cross platform on Android, iOS, macOS, tvOS, Linux, Windows and modern web browsers.
https://superpowered.com
1.34k stars 285 forks source link

How to implement pitch detection (getNotes() ?) on iOS ? #783

Closed happyriri closed 2 months ago

happyriri commented 2 months ago

Hi !

How to implement pitch detection (getNotes() ?) on iOS ?

I don't see any informations on the documentation.

Thanks !

ivannador commented 2 months ago

Hello!

The class LiveAnalyzer will help you achieve what you need.

Please find the relevant documentation here: https://docs.superpowered.com/reference/latest/live-analyzer?lang=cpp The iOS integration guide can be found here: https://docs.superpowered.com/getting-started/how-to-integrate/ios?lang=cpp

Hope this helps!

Ivan

happyriri commented 2 months ago

Thanks for your help !

I have this code in my SuperpoweredBridge Objective-C++ :

#include "Superpowered.h"
#include "SuperpoweredSimple.h"
#import "SuperpoweredBridge.h"
#import "../libs/Superpowered/SuperpoweredAnalyzer.h"
#import "SuperpoweredIOSAudioIO.h"

@implementation SuperpoweredBridge {
    SuperpoweredIOSAudioIO *audioIO;
    Superpowered::LiveAnalyzer *analyzer;
}

static bool audioProcessing(void *clientdata, float *input, float *output, unsigned int numberOfFrames, unsigned int samplerate, uint64_t hostTime) {
    __unsafe_unretained SuperpoweredBridge *self = (__bridge SuperpoweredBridge *)clientdata;
    //printf("numberOfFrames : %d", numberOfFrames);
    self->analyzer->process(input, numberOfFrames);
    if (self->analyzer->keyIndex == -1) {
        printf("Unkown");
    } else {
        printf("Note : %s ", Superpowered::musicalChordNames[self->analyzer->keyIndex]);
    }
    return false;
}

- (id)init {
    self = [super init];
    if (!self) return nil;
    Superpowered::Initialize("ExampleLicenseKey-WillExpire-OnNextUpdate");

    analyzer = new Superpowered::LiveAnalyzer(
        44100
    );

    audioIO = [[SuperpoweredIOSAudioIO alloc] initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)self preferredBufferSize:12 preferredSamplerate:44100 audioSessionCategory:AVAudioSessionCategoryRecord channels:2 audioProcessingCallback:audioProcessing clientdata:(__bridge void *)self];
    [audioIO start];
    return self;
}

- (void)dealloc {
    delete analyzer;
    audioIO = nil;
}

@end

I get a note output but only once every x seconds. And sometime the note is -1.

Can you help me ?

Thanks

ivannador commented 2 months ago

Your code seems fine, but you should make sure to set the actual sample rate of the LiveAnalyzer in the process call.

According to the docs: The update frequency is 2 seconds. So it is expected to only have a result each 2 seconds. -1 means the LiveAnalyzer could not find the dominant key in that chunk. Make sure to set the actual sample rate, that might help.

happyriri commented 2 months ago

Oh so Superpowered only show results every 2 seconds ??! This is not as speed as I thought ! :(

I want real time pitch detection (multiple results every second), have you the possibiliy to do so ?

Thanks again for all you help !

ivannador commented 2 months ago

The Superpowered LiveAnalyzer's purpose is more oriented towards detecting the dominant key of music instead of the lowest possible latency pitch detection for singing for example. With that said, Superpowered provides high performance FFT utilities to implement your own pitch detection algorithms or you can easily interface a C++-based third party real-time pitch detection algorithm with Superpowered.