Announcement

Collapse
No announcement yet.

VLF MD with digital signal processing : Bee-Buzz 1

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • dbanner
    replied
    next, I requested a complete framework. And here is the reply:

    Writing a complete firmware for a metal detector based on an STM32 microcontroller is a complex task that involves hardware-specific configurations, signal processing algorithms, and user interface implementation. Below, I'll provide a simplified framework for such a firmware. This framework will include:
    1. Hardware Initialization (e.g., GPIO, ADC, timers, DMA).
    2. Signal Processing (e.g., filtering, target detection).
    3. User Interface (e.g., LCD, buttons, sound feedback).
    4. Main Loop for real-time operation.

    This example assumes you're using an STM32 microcontroller with ARM Cortex-M3/M4, and it uses the STM32 HAL library for hardware abstraction. You'll need to adapt it to your specific hardware and requirements.
    Complete Firmware Framework

    ​#include "stm32f1xx_hal.h" // Replace with your STM32 series header
    #include <arm_math.h> // CMSIS-DSP library for signal processing
    #include <cstring> // For memset, memcpy

    // Constants and Configuration
    #define SAMPLE_RATE 10000 // 10 kHz sampling rate
    #define BUFFER_SIZE 256 // Sample buffer size
    #define TARGET_THRESHOLD 1000 // Threshold for target detection
    #define FILTER_ORDER 5 // FIR filter order

    // Global Variables
    volatile uint16_t adc_buffer[BUFFER_SIZE]; // ADC sample buffer
    volatile bool target_detected = false; // Target detection flag
    char lcd_buffer[16]; // LCD display buffer

    // FIR Filter Coefficients (example coefficients)
    const float32_t fir_coeff[FILTER_ORDER] = {0.1, 0.2, 0.4, 0.2, 0.1};

    // FIR Filter Instance
    arm_fir_instance_f32 fir_instance;
    float32_t fir_state[BUFFER_SIZE + FILTER_ORDER - 1];

    // Function Prototypes
    void SystemClock_Config(void);
    void GPIO_Init(void);
    void ADC_Init(void);
    void DMA_Init(void);
    void TIM_Init(void);
    void LCD_Init(void);
    void LCD_Display(const char* text);
    void Process_Samples(uint16_t* samples, uint16_t size);
    void Beep(uint16_t frequency, uint16_t duration);

    // Main Function
    int main(void) {
    // HAL Initialization
    HAL_Init();
    SystemClock_Config();

    // Peripheral Initialization
    GPIO_Init();
    ADC_Init();
    DMA_Init();
    TIM_Init();
    LCD_Init();

    // Initialize FIR Filter
    arm_fir_init_f32(&fir_instance, FILTER_ORDER, (float32_t*)fir_coeff, fir_state, BUFFER_SIZE);

    // Start ADC with DMA
    HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, BUFFER_SIZE);

    // Main Loop
    while (1) {
    // Wait for ADC buffer to be filled
    if (HAL_ADC_PollForConversion(&hadc, 100) == HAL_OK) {
    // Process samples
    Process_Samples((uint16_t*)adc_buffer, BUFFER_SIZE);

    // Display result on LCD
    if (target_detected) {
    LCD_Display("Target Found!");
    Beep(1000, 200); // Beep for 200ms at 1kHz
    } else {
    LCD_Display("No Target");
    }
    }
    }
    }

    // Process ADC Samples
    void Process_Samples(uint16_t* samples, uint16_t size) {
    float32_t input[BUFFER_SIZE], output[BUFFER_SIZE];

    // Convert ADC samples to float
    for (uint16_t i = 0; i < size; i++) {
    input[i] = (float32_t)samples[i];
    }

    // Apply FIR Filter
    arm_fir_f32(&fir_instance, input, output, size);

    // Detect target (simple thresholding)
    float32_t max_value = 0;
    arm_max_f32(output, size, &max_value, NULL);

    if (max_value > TARGET_THRESHOLD) {
    target_detected = true;
    } else {
    target_detected = false;
    }
    }

    // Beep Function (using PWM or timer)
    void Beep(uint16_t frequency, uint16_t duration) {
    // Configure timer for PWM to generate a tone
    // Example: Use TIM2 to generate a square wave at the desired frequency
    __HAL_TIM_SET_AUTORELOAD(&htim2, (SystemCoreClock / frequency) - 1);
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (SystemCoreClock / frequency) / 2);
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

    // Wait for the duration
    HAL_Delay(duration);

    // Stop PWM
    HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
    }

    // LCD Display Function
    void LCD_Display(const char* text) {
    // Clear LCD buffer
    memset(lcd_buffer, 0, sizeof(lcd_buffer));

    // Copy text to LCD buffer
    strncpy(lcd_buffer, text, 15);

    // Send buffer to LCD (implementation depends on your LCD hardware)
    // Example: Send via I2C or GPIO
    }

    // Hardware Initialization Functions
    void GPIO_Init(void) {
    // Initialize GPIO pins for buttons, LEDs, etc.
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_5; // Example: LED on PA5
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }

    void ADC_Init(void) {
    // Initialize ADC for sampling
    __HAL_RCC_ADC1_CLK_ENABLE();
    ADC_ChannelConfTypeDef sConfig = {0};
    hadc.Instance = ADC1;
    hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc.Init.ContinuousConvMode = ENABLE;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.NbrOfConversion = 1;
    HAL_ADC_Init(&hadc);

    // Configure ADC channel
    sConfig.Channel = ADC_CHANNEL_0; // Example: Use ADC channel 0
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    }

    void DMA_Init(void) {
    // Initialize DMA for ADC
    __HAL_RCC_DMA1_CLK_ENABLE();
    hdma_adc.Instance = DMA1_Channel1;
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc.Init.Mode = DMA_CIRCULAR;
    hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_adc);

    // Link DMA to ADC
    __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc);
    }

    void TIM_Init(void) {
    // Initialize timer for PWM (beep)
    __HAL_RCC_TIM2_CLK_ENABLE();
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 0;
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 0;
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_PWM_Init(&htim2);

    // Configure PWM channel
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
    }

    void LCD_Init(void) {
    // Initialize LCD (implementation depends on your LCD hardware)
    // Example: Use I2C or GPIO to communicate with the LCD
    }

    // System Clock Configuration
    void SystemClock_Config(void) {
    // Configure system clock (e.g., 72 MHz for STM32F1)
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
    }​
    Key Features of the Firmware:
    1. ADC Sampling:
      • Uses DMA to continuously sample data from the ADC.
    2. Signal Processing:
      • Applies an FIR filter to the sampled data and detects targets using a simple threshold.
    3. User Feedback:
      • Displays results on an LCD and provides audio feedback (beep) when a target is detected.
    4. Real-Time Operation:
      • Runs in a continuous loop, processing data in real-time.

    Next Steps:
    1. Adapt to Your Hardware:
      • Replace placeholders (e.g., hadc, htim2) with your actual peripheral handles.
    2. Enhance Signal Processing:
      • Implement more advanced algorithms (e.g., FFT, IIR filters) for better target discrimination.
    3. Add User Controls:
      • Implement buttons or a menu system for user interaction.
    4. Test and Debug:
      • Use a debugger (e.g., ST-Link) to verify the firmware's behavior.

    Let me know if you need further assistance or specific parts of the firmware explained in more detail!
    ​

    Leave a comment:


  • dbanner
    replied
    This was deepseek's reply:



    Optimizing code for a metal detector using DSP on an STM32 microcontroller involves several considerations, such as reducing computational overhead, improving memory usage, and ensuring real-time performance. Below, I'll provide some general optimizations and specific suggestions for your code. Since I don't have the full context of your project, I'll focus on improving the structure, efficiency, and readability of the provided code.
    General Optimizations:
    1. Minimize Global Variables:
      • Global variables increase memory usage and can lead to slower access times. Use local variables where possible, and pass data via function parameters.
    2. Use const for Constants:
      • Mark constant data (e.g., filter coefficients) as const to allow the compiler to optimize memory usage.
    3. Optimize Loops:
      • Avoid unnecessary computations inside loops. For example, precompute values outside the loop if they don't change.
    4. Use Efficient Data Types:
      • Use the smallest data type that can hold the required values (e.g., uint8_t instead of int if the range allows).
    5. Enable Compiler Optimizations:
      • Use compiler flags like -O2 or -O3 for ARM Cortex-M3 to enable optimizations.
    6. Reduce Function Calls:
      • Inline small, frequently called functions to reduce overhead.
    7. Use DMA Efficiently:
      • Ensure DMA is configured for maximum throughput and minimal CPU intervention.

    Specific Optimizations for Your Code:

    1. Memory Initialization:
    • Instead of using a loop to clear memory, consider using memset for better readability and potential optimization by the compiler.
    cpp
    Copymemset((void*)0x20000000, 0, 0x2000); // Clear memory 2. Filter Initialization:
    • Use const for filter coefficients and ensure they are stored in flash memory to save RAM.
    cpp
    Copystatic const q31_t filter_coef[7] = {
    0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
    }; 3. Task Creation:
    • Check the stack sizes for tasks. Ensure they are not unnecessarily large, as this wastes memory.
    cpp
    Copyif (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 0);
    } 4. Avoid Redundant Initializations:
    • Ensure that variables like USER_ID, sound_tone, and sample_count are only initialized once if they don't need to be reset.
    5. Use volatile Sparingly:
    • Only use volatile for variables that are modified outside the current execution context (e.g., by interrupts or DMA).
    6. Optimize DSP Functions:
    • Use ARM CMSIS-DSP library functions efficiently. For example, ensure that arm_fir_init_q31 is used to initialize FIR filters instead of manually setting up the structure.
    cpp
    Copyarm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
    arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32); 7. Reduce Critical Sections:
    • Minimize the use of taskDISABLE_INTERRUPTS and taskENABLE_INTERRUPTS to avoid long periods of interrupt blocking.
    8. Optimize LCD Updates:
    • Update the LCD only when necessary, and avoid frequent calls to memcpy for the LCD buffers.

    Optimized Code Example:


    Here’s a refactored version of your main function with some of the above optimizations applied:

    cpp
    Copyint main(void) {
    SystemInit();
    RCC_Init();
    start_1us_timer();
    io_init();

    // Clear memory
    memset((void*)0x20000000, 0, 0x2000);

    // Initialize LCD buffers
    memcpy(LCD_first_string, " Quasar ARM ", 16);
    memcpy(LCD_second_string, " ver. 2.6.5M ", 16);

    // Initialize variables
    USER_ID = -100; // Invalid value
    sound_tone = 1000;

    // Initialize FIR filters
    static const q31_t filter_coef[7] = {
    0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
    };

    arm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
    arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32);

    // Initialize menu
    menu_pointer = &null_menu;

    // Initialize peripherals
    lcd_init();
    start_led_blink();
    check_HSE();
    check_pullup_resistors();
    TIM15_init();
    setup_TIM2_3_4();
    init_sound_DAC_DMA_TIMER();
    init_compensator();
    setup_DMA_ADC();
    reset_I2C_bus();
    load_profile();
    ICALL_sub_menu_10(&menu_xref_audio);

    // Create mutexes and tasks
    MUTEX_SOUND = xSemaphoreCreateMutex();
    MUTEX_LCD = xSemaphoreCreateMutex();

    if (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 0);
    }
    if (pdTRUE != xTaskCreate(task_PROCESS, "PROCESS", 108, NULL, 4, &handle_PROCESS)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 1);
    }
    if (pdTRUE != xTaskCreate(task_LCD, "LCD", 60, NULL, 1, NULL)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 2);
    }
    if (pdTRUE != xTaskCreate(task_MENU, "MENU", 150, NULL, 2, NULL)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 3);
    }

    // Start scheduler
    vTaskStartScheduler();
    for (;;
    }
    Additional Recommendations:
    1. Profile Your Code:
      • Use a profiler to identify bottlenecks in your code. Focus on optimizing the most time-consuming functions.
    2. Use Hardware Features:
      • Leverage STM32 hardware features like the FPU (if available) for faster DSP computations.
    3. Test and Validate:
      • After making optimizations, thoroughly test the system to ensure that performance improvements do not introduce bugs or reduce accuracy.
    4. Consider Power Consumption:
      • Optimize for low power usage if the metal detector is battery-powered. Use low-power modes when idle.

    Let me know if you need further assistance!

    ​


    ​

    Leave a comment:


  • dbanner
    replied
    Originally posted by moodz View Post
    ​​​​​​I will dig it out for you.

    Here it is .... though my book is called Signal Processing Algorithms in Fortran and C
    .... So my copy is the later book .. an expanded version of the one above (c 1988 )
    Thanks.
    I was able to get the '88 edition.

    On another subject, I asked deepseek to optimize some code and it refactored it with ease, even providing a step by step account of each optimization along with explanation. It spit out the new code:

    int main(void) {
    SystemInit();
    RCC_Init();
    start_1us_timer();
    io_init();

    // Clear memory
    memset((void*)0x20000000, 0, 0x2000);

    // Initialize LCD buffers
    memcpy(LCD_first_string, " Quasar ARM ", 16);
    memcpy(LCD_second_string, " ver. 2.6.5M ", 16);

    // Initialize variables
    USER_ID = -100; // Invalid value
    sound_tone = 1000;

    // Initialize FIR filters
    static const q31_t filter_coef[7] = {
    0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
    };

    arm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
    arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32);

    // Initialize menu
    menu_pointer = &null_menu;

    // Initialize peripherals
    lcd_init();
    start_led_blink();
    check_HSE();
    check_pullup_resistors();
    TIM15_init();
    setup_TIM2_3_4();
    init_sound_DAC_DMA_TIMER();
    init_compensator();
    setup_DMA_ADC();
    reset_I2C_bus();
    load_profile();
    ICALL_sub_menu_10(&menu_xref_audio);

    // Create mutexes and tasks
    MUTEX_SOUND = xSemaphoreCreateMutex();
    MUTEX_LCD = xSemaphoreCreateMutex();

    if (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 0);
    }
    if (pdTRUE != xTaskCreate(task_PROCESS, "PROCESS", 108, NULL, 4, &handle_PROCESS)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 1);
    }
    if (pdTRUE != xTaskCreate(task_LCD, "LCD", 60, NULL, 1, NULL)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 2);
    }
    if (pdTRUE != xTaskCreate(task_MENU, "MENU", 150, NULL, 2, NULL)) {
    ERROR_ACTION(QUEUE_NOT_CREATE, 3);
    }

    // Start scheduler
    vTaskStartScheduler();
    for (; ;
    }

    Leave a comment:


  • Aziz
    replied
    Oh no!

    I have installed the latest Android Studio on my Surface Tablet 4. Did a new empty project and run it (any phone simulation). After GB's of download and working hot at 100 % CPU and waiting 30 minutes, I finally gave it up.
    WTF is doing Google? I want to see my App running! And debugging! Instantly!
    KISS! KISS! KISS!
    Google KISS my Ašš!

    It is going to be difficult making Android Apps for me. Maybe I need a 32 core cpu with 32 GB RAM at 5 GHz. So I will stay at Windows platforms at the moment.

    Btw, viewing a movie on my surface tablet takes only 1 % of CPU time. This is the goal for my detector software. Extremely power efficient light weight Win32 App. No FFT. Minimum GUI and graphics output.

    Cheers
    Aziz

    Leave a comment:


  • moodz
    replied
    Originally posted by dbanner View Post
    Does anyone have the floppy disk file which accompanied this book?

    Click image for larger version  Name:	Screenshot(180).gif Views:	0 Size:	248.5 KB ID:	433492
    ​​​​​​I will dig it out for you.

    Here it is .... though my book is called Signal Processing Algorithms in Fortran and C
    .... So my copy is the later book .. an expanded version of the one above (c 1988 )
    Attached Files
    Last edited by moodz; 01-28-2025, 10:00 PM. Reason: added file

    Leave a comment:


  • Aziz
    replied
    Hi all,

    I'm going to buy the Creative Sound Blaster G3 soon. I was confused with the Sound Blaster Play xxx devices, which won't be appropriate for the project. Headset plug only is no-go (4 pole TRRS)!

    But the G3 has true line input (combo plug with digital input). And it has ear phone output (no line out). But only 24 bit @96 kHz SR. It can be plugged into an Android device (Android 8 +). The G3 is cheap, lightweight and small. Perfect for some testing.
    Aziz
    ​

    Leave a comment:


  • dbanner
    replied
    Does anyone have the floppy disk file which accompanied this book?

    Click image for larger version

Name:	Screenshot(180).gif
Views:	303
Size:	248.5 KB
ID:	433492

    Leave a comment:


  • moodz
    replied
    Were just AI's ...this is how we learn.

    Leave a comment:


  • dbanner
    replied
    Huh, you guys don't pull your punches, do you.

    And Moodz, how the hell do you know so much?

    Leave a comment:


  • Aziz
    replied
    Originally posted by moodz View Post
    Well if you don’t want a supa dupa detector you are in the right place
    Super-Duper-Oreshnik-Detector!

    Leave a comment:


  • moodz
    replied
    Well if you don’t want a supa dupa detector you are in the right place

    Leave a comment:


  • Aziz
    replied
    Btw,

    the mic input is often band limitted (up to 8-10 kHz). Or modified with DSP functions (noise suppression, echo chancellation, ...). It is biased with a DC voltage to realise some functions:
    Mute, play, pause and so on by a simple pull down resistor switches.

    But in general, a simplied detector would still be possible. Even with Headset plug (Stereo output + mono mic input). All effects must be switched off so the signal data wont get modified. Stereo output will drive on one channel the TX coil and on the other channel beep output. And we would have some latency to beep output sound. Or take the internal sound part of the device (Tablet or smartphone).
    As we have no reference to TX phase info, we must implement a motion mode detector.

    So in general it is possible if we dont want a super-duper detector.
    Aziz

    Leave a comment:


  • Aziz
    replied
    Hi Moodz,

    the Sound Blaster 4 Play is totally useless for my App.
    No 2-ch line input. Reduced sampling rate (48 kHz).
    I dont use mic inputs.
    I need two channels (signal and reference) line inputs for clean an stable decoding.
    The head-set input with mono mic input is not a good solution.
    Aziz

    Leave a comment:


  • moodz
    replied
    Originally posted by Aziz View Post
    Hi all,

    this is a good video introduction for an AAudio API. Its nearly same principle on Windows systems.

    Best practices for Android Audio (Google I/O '17)


    Again, will a 6 inch Android tablet or Android smartphone accept an external USB sound card for signal processing (USB Audio Class 2)? I dont know the answer yet.
    Aziz

    Well thats some time I wont get back again LOL

    USB audio dongles that are compliant with the USB Audio Standard will work with android. To verify if your phone is compliant with the USB Audio Standard, you will have to approach your mobile device's manufacturer.​

    Dunno about the soundblaster you have ... but the SoundBlaster 4 Play works directly with Android phones version 8+ ... cheap as chips too.

    Click image for larger version  Name:	image.png Views:	0 Size:	154.0 KB ID:	433468​

    Leave a comment:


  • moodz
    replied
    The NDK is not a wrapper its more of a Java ByPass direct access to CPU.

    It's called the NDK "NATIVE" development kit for a reason... DSP code written in C/Cpp is much more efficient than java code because the code runs directly on the CPU.
    The Native Development Kit (NDK) is a set of tools provided by Google for Android developers. It allows developers to incorporate native code written in languages like C and C++ into their Android applications. Unlike Java, which runs on the Android Runtime (ART) virtual machine, native code compiled with the NDK runs directly on the device’s CPU, offering performance benefits for computationally intensive tasks.

    By leveraging the NDK, developers can optimize performance, access platform-specific features, and reuse existing C/C++ libraries in their Android apps. The NDK provides toolchains, libraries, and build system integration to streamline the development process and enable seamless communication between native code and Java components using the Java Native Interface (JNI).
    ​
    Last edited by moodz; 01-26-2025, 11:53 PM.

    Leave a comment:

Working...
X