You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
IoT-For-Beginners/translations/ro/6-consumer/lessons/1-speech-recognition/wio-terminal-audio.md

26 KiB

Capturarea audio - Wio Terminal

În această parte a lecției, vei scrie cod pentru a captura audio pe Wio Terminal. Capturarea audio va fi controlată de unul dintre butoanele de pe partea superioară a dispozitivului Wio Terminal.

Programează dispozitivul pentru a captura audio

Poți captura audio de la microfon folosind cod C++. Wio Terminal are doar 192KB de RAM, insuficient pentru a captura mai mult de câteva secunde de audio. Totuși, are 4MB de memorie flash, care poate fi utilizată pentru a salva audio-ul capturat.

Microfonul încorporat captează un semnal analogic, care este convertit într-un semnal digital utilizabil de Wio Terminal. Când capturezi audio, datele trebuie capturate la momentul potrivit - de exemplu, pentru a captura audio la 16KHz, trebuie să captezi exact 16.000 de mostre pe secundă, la intervale egale. În loc să folosești codul tău pentru a face acest lucru, poți utiliza controlerul de acces direct la memorie (DMAC). Acesta este un circuit care poate captura un semnal și îl poate scrie în memorie, fără a întrerupe codul care rulează pe procesor.

Citește mai multe despre DMA pe pagina despre accesul direct la memorie de pe Wikipedia.

Audio-ul de la microfon merge la un ADC, apoi la DMAC. Acesta scrie într-un buffer. Când acest buffer este plin, este procesat, iar DMAC scrie într-un al doilea buffer

DMAC poate captura audio de la ADC la intervale fixe, cum ar fi de 16.000 de ori pe secundă pentru audio la 16KHz. Poate scrie aceste date capturate într-un buffer de memorie pre-alocat, iar când acesta este plin, îl face disponibil pentru procesarea codului tău. Utilizarea acestei memorii poate întârzia capturarea audio, dar poți configura mai multe buffere. DMAC scrie în bufferul 1, iar când acesta este plin, notifică codul tău să proceseze bufferul 1, în timp ce DMAC scrie în bufferul 2. Când bufferul 2 este plin, notifică codul tău și revine la scrierea în bufferul 1. Astfel, atâta timp cât procesezi fiecare buffer într-un timp mai scurt decât cel necesar pentru a umple unul, nu vei pierde date.

Odată ce fiecare buffer a fost capturat, acesta poate fi scris în memoria flash. Memoria flash trebuie scrisă folosind adrese definite, specificând unde și cât de mult să scrii, similar cu actualizarea unui array de bytes în memorie. Memoria flash are granularitate, ceea ce înseamnă că operațiunile de ștergere și scriere depind nu doar de o dimensiune fixă, ci și de alinierea la acea dimensiune. De exemplu, dacă granularitatea este de 4096 bytes și soliciți o ștergere la adresa 4200, aceasta ar putea șterge toate datele de la adresa 4096 la 8192. Acest lucru înseamnă că atunci când scrii datele audio în memoria flash, trebuie să fie în bucăți de dimensiunea corectă.

Sarcină - configurarea memoriei flash

  1. Creează un proiect nou pentru Wio Terminal folosind PlatformIO. Denumește acest proiect smart-timer. Adaugă cod în funcția setup pentru a configura portul serial.

  2. Adaugă următoarele dependențe de bibliotecă în fișierul platformio.ini pentru a avea acces la memoria flash:

    lib_deps =
        seeed-studio/Seeed Arduino FS @ 2.1.1
        seeed-studio/Seeed Arduino SFUD @ 2.0.2
    
  3. Deschide fișierul main.cpp și adaugă următoarea directivă de includere pentru biblioteca de memorie flash în partea de sus a fișierului:

    #include <sfud.h>
    #include <SPI.h>
    

    🎓 SFUD înseamnă Serial Flash Universal Driver și este o bibliotecă proiectată să funcționeze cu toate cipurile de memorie flash.

  4. În funcția setup, adaugă următorul cod pentru a configura biblioteca de stocare flash:

    while (!(sfud_init() == SFUD_SUCCESS))
        ;
    
    sfud_qspi_fast_read_enable(sfud_get_device(SFUD_W25Q32_DEVICE_INDEX), 2);
    

    Acest cod rulează în buclă până când biblioteca SFUD este inițializată, apoi activează citirile rapide. Memoria flash încorporată poate fi accesată folosind o Interfață Serială Periferică Cu Cozi (QSPI), un tip de controler SPI care permite acces continuu printr-o coadă cu utilizare minimă a procesorului. Acest lucru face ca citirea și scrierea în memoria flash să fie mai rapide.

  5. Creează un fișier nou în folderul src numit flash_writer.h.

  6. Adaugă următoarele la începutul acestui fișier:

    #pragma once
    
    #include <Arduino.h>
    #include <sfud.h>
    

    Acest lucru include câteva fișiere header necesare, inclusiv fișierul header pentru biblioteca SFUD pentru a interacționa cu memoria flash.

  7. Definește o clasă în acest nou fișier header numită FlashWriter:

    class FlashWriter
    {
    public:
    
    private:
    };
    
  8. În secțiunea private, adaugă următorul cod:

    byte *_sfudBuffer;
    size_t _sfudBufferSize;
    size_t _sfudBufferPos;
    size_t _sfudBufferWritePos;
    
    const sfud_flash *_flash;
    

    Acest cod definește câmpuri pentru bufferul utilizat pentru a stoca datele înainte de a le scrie în memoria flash. Este prezent un array de bytes, _sfudBuffer, pentru a scrie datele, iar când acesta este plin, datele sunt scrise în memoria flash. Câmpul _sfudBufferPos stochează locația curentă pentru scriere în acest buffer, iar _sfudBufferWritePos stochează locația din memoria flash pentru scriere. _flash este un pointer către memoria flash în care se scrie - unele microcontrolere au mai multe cipuri de memorie flash.

  9. Adaugă următoarea metodă în secțiunea public pentru a inițializa această clasă:

    void init()
    {
        _flash = sfud_get_device_table() + 0;
        _sfudBufferSize = _flash->chip.erase_gran;
        _sfudBuffer = new byte[_sfudBufferSize];
        _sfudBufferPos = 0;
        _sfudBufferWritePos = 0;
    }
    

    Aceasta configurează memoria flash de pe Wio Terminal pentru scriere și setează bufferele pe baza dimensiunii granulelor memoriei flash. Este într-o metodă init, mai degrabă decât un constructor, deoarece trebuie apelată după ce memoria flash a fost configurată în funcția setup.

  10. Adaugă următorul cod în secțiunea public:

    void writeSfudBuffer(byte b)
    {
        _sfudBuffer[_sfudBufferPos++] = b;
        if (_sfudBufferPos == _sfudBufferSize)
        {
            sfud_erase_write(_flash, _sfudBufferWritePos, _sfudBufferSize, _sfudBuffer);
            _sfudBufferWritePos += _sfudBufferSize;
            _sfudBufferPos = 0;
        }
    }
    
    void writeSfudBuffer(byte *b, size_t len)
    {
        for (size_t i = 0; i < len; ++i)
        {
            writeSfudBuffer(b[i]);
        }
    }
    
    void flushSfudBuffer()
    {
        if (_sfudBufferPos > 0)
        {
            sfud_erase_write(_flash, _sfudBufferWritePos, _sfudBufferSize, _sfudBuffer);
            _sfudBufferWritePos += _sfudBufferSize;
            _sfudBufferPos = 0;
        }
    }
    

    Acest cod definește metode pentru a scrie bytes în sistemul de stocare flash. Funcționează prin scrierea într-un buffer în memorie care are dimensiunea corectă pentru memoria flash, iar când acesta este plin, este scris în memoria flash, ștergând orice date existente la acea locație. Există și o metodă flushSfudBuffer pentru a scrie un buffer incomplet, deoarece datele capturate nu vor fi multipli exacți ai dimensiunii granulelor, astfel încât partea finală a datelor trebuie scrisă.

    💁 Partea finală a datelor va scrie date suplimentare nedorite, dar acest lucru este în regulă, deoarece doar datele necesare vor fi citite.

Sarcină - configurarea capturii audio

  1. Creează un fișier nou în folderul src numit config.h.

  2. Adaugă următoarele la începutul acestui fișier:

    #pragma once
    
    #define RATE 16000
    #define SAMPLE_LENGTH_SECONDS 4
    #define SAMPLES RATE * SAMPLE_LENGTH_SECONDS
    #define BUFFER_SIZE (SAMPLES * 2) + 44
    #define ADC_BUF_LEN 1600
    

    Acest cod configurează câteva constante pentru capturarea audio.

    Constantă Valoare Descriere
    RATE 16000 Rata de eșantionare pentru audio. 16.000 este 16KHz
    SAMPLE_LENGTH_SECONDS 4 Durata audio-ului capturat. Este setată la 4 secunde. Pentru a înregistra mai mult, mărește această valoare.
    SAMPLES 64000 Numărul total de mostre audio care vor fi capturate. Setat la rata de eșantionare * numărul de secunde
    BUFFER_SIZE 128044 Dimensiunea bufferului audio pentru capturare. Audio-ul va fi capturat ca un fișier WAV, care are 44 bytes de header, apoi 128.000 bytes de date audio (fiecare mostră are 2 bytes)
    ADC_BUF_LEN 1600 Dimensiunea bufferelor utilizate pentru a captura audio de la DMAC

    💁 Dacă consideri că 4 secunde sunt prea puține pentru a solicita un timer, poți mări valoarea SAMPLE_LENGTH_SECONDS, iar toate celelalte valori vor fi recalculate.

  3. Creează un fișier nou în folderul src numit mic.h.

  4. Adaugă următoarele la începutul acestui fișier:

    #pragma once
    
    #include <Arduino.h>
    
    #include "config.h"
    #include "flash_writer.h"
    

    Acest lucru include câteva fișiere header necesare, inclusiv fișierele config.h și FlashWriter.

  5. Adaugă următoarele pentru a defini o clasă Mic care poate captura de la microfon:

    class Mic
    {
    public:
        Mic()
        {
            _isRecording = false;
            _isRecordingReady = false;
        }
    
        void startRecording()
        {
            _isRecording = true;
            _isRecordingReady = false;
        }
    
        bool isRecording()
        {
            return _isRecording;
        }
    
        bool isRecordingReady()
        {
            return _isRecordingReady;
        }
    
    private:
        volatile bool _isRecording;
        volatile bool _isRecordingReady;
        FlashWriter _writer;
    };
    
    Mic mic;
    

    Această clasă are în prezent doar câteva câmpuri pentru a urmări dacă înregistrarea a început și dacă o înregistrare este gata de utilizare. Când DMAC este configurat, acesta scrie continuu în bufferele de memorie, astfel încât flag-ul _isRecording determină dacă acestea ar trebui procesate sau ignorate. Flag-ul _isRecordingReady va fi setat când cele 4 secunde necesare de audio au fost capturate. Câmpul _writer este utilizat pentru a salva datele audio în memoria flash.

    Este apoi declarată o variabilă globală pentru o instanță a clasei Mic.

  6. Adaugă următorul cod în secțiunea private a clasei Mic:

    typedef struct
    {
        uint16_t btctrl;
        uint16_t btcnt;
        uint32_t srcaddr;
        uint32_t dstaddr;
        uint32_t descaddr;
    } dmacdescriptor;
    
    // Globals - DMA and ADC
    volatile dmacdescriptor _wrb[DMAC_CH_NUM] __attribute__((aligned(16)));
    dmacdescriptor _descriptor_section[DMAC_CH_NUM] __attribute__((aligned(16)));
    dmacdescriptor _descriptor __attribute__((aligned(16)));
    
    void configureDmaAdc()
    {
        // Configure DMA to sample from ADC at a regular interval (triggered by timer/counter)
        DMAC->BASEADDR.reg = (uint32_t)_descriptor_section;                    // Specify the location of the descriptors
        DMAC->WRBADDR.reg = (uint32_t)_wrb;                                    // Specify the location of the write back descriptors
        DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf);           // Enable the DMAC peripheral
        DMAC->Channel[1].CHCTRLA.reg = DMAC_CHCTRLA_TRIGSRC(TC5_DMAC_ID_OVF) | // Set DMAC to trigger on TC5 timer overflow
                                        DMAC_CHCTRLA_TRIGACT_BURST;             // DMAC burst transfer
    
        _descriptor.descaddr = (uint32_t)&_descriptor_section[1];                    // Set up a circular descriptor
        _descriptor.srcaddr = (uint32_t)&ADC1->RESULT.reg;                           // Take the result from the ADC0 RESULT register
        _descriptor.dstaddr = (uint32_t)_adc_buf_0 + sizeof(uint16_t) * ADC_BUF_LEN; // Place it in the adc_buf_0 array
        _descriptor.btcnt = ADC_BUF_LEN;                                             // Beat count
        _descriptor.btctrl = DMAC_BTCTRL_BEATSIZE_HWORD |                            // Beat size is HWORD (16-bits)
                                DMAC_BTCTRL_DSTINC |                                    // Increment the destination address
                                DMAC_BTCTRL_VALID |                                     // Descriptor is valid
                                DMAC_BTCTRL_BLOCKACT_SUSPEND;                           // Suspend DMAC channel 0 after block transfer
        memcpy(&_descriptor_section[0], &_descriptor, sizeof(_descriptor));          // Copy the descriptor to the descriptor section
    
        _descriptor.descaddr = (uint32_t)&_descriptor_section[0];                    // Set up a circular descriptor
        _descriptor.srcaddr = (uint32_t)&ADC1->RESULT.reg;                           // Take the result from the ADC0 RESULT register
        _descriptor.dstaddr = (uint32_t)_adc_buf_1 + sizeof(uint16_t) * ADC_BUF_LEN; // Place it in the adc_buf_1 array
        _descriptor.btcnt = ADC_BUF_LEN;                                             // Beat count
        _descriptor.btctrl = DMAC_BTCTRL_BEATSIZE_HWORD |                            // Beat size is HWORD (16-bits)
                                DMAC_BTCTRL_DSTINC |                                    // Increment the destination address
                                DMAC_BTCTRL_VALID |                                     // Descriptor is valid
                                DMAC_BTCTRL_BLOCKACT_SUSPEND;                           // Suspend DMAC channel 0 after block transfer
        memcpy(&_descriptor_section[1], &_descriptor, sizeof(_descriptor));          // Copy the descriptor to the descriptor section
    
        // Configure NVIC
        NVIC_SetPriority(DMAC_1_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for DMAC1 to 0 (highest)
        NVIC_EnableIRQ(DMAC_1_IRQn);      // Connect DMAC1 to Nested Vector Interrupt Controller (NVIC)
    
        // Activate the suspend (SUSP) interrupt on DMAC channel 1
        DMAC->Channel[1].CHINTENSET.reg = DMAC_CHINTENSET_SUSP;
    
        // Configure ADC
        ADC1->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_AIN12_Val; // Set the analog input to ADC0/AIN2 (PB08 - A4 on Metro M4)
        while (ADC1->SYNCBUSY.bit.INPUTCTRL)
            ;                              // Wait for synchronization
        ADC1->SAMPCTRL.bit.SAMPLEN = 0x00; // Set max Sampling Time Length to half divided ADC clock pulse (2.66us)
        while (ADC1->SYNCBUSY.bit.SAMPCTRL)
            ;                                         // Wait for synchronization
        ADC1->CTRLA.reg = ADC_CTRLA_PRESCALER_DIV128; // Divide Clock ADC GCLK by 128 (48MHz/128 = 375kHz)
        ADC1->CTRLB.reg = ADC_CTRLB_RESSEL_12BIT |    // Set ADC resolution to 12 bits
                            ADC_CTRLB_FREERUN;          // Set ADC to free run mode
        while (ADC1->SYNCBUSY.bit.CTRLB)
            ;                       // Wait for synchronization
        ADC1->CTRLA.bit.ENABLE = 1; // Enable the ADC
        while (ADC1->SYNCBUSY.bit.ENABLE)
            ;                       // Wait for synchronization
        ADC1->SWTRIG.bit.START = 1; // Initiate a software trigger to start an ADC conversion
        while (ADC1->SYNCBUSY.bit.SWTRIG)
            ; // Wait for synchronization
    
        // Enable DMA channel 1
        DMAC->Channel[1].CHCTRLA.bit.ENABLE = 1;
    
        // Configure Timer/Counter 5
        GCLK->PCHCTRL[TC5_GCLK_ID].reg = GCLK_PCHCTRL_CHEN |     // Enable peripheral channel for TC5
                                            GCLK_PCHCTRL_GEN_GCLK1; // Connect generic clock 0 at 48MHz
    
        TC5->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; // Set TC5 to Match Frequency (MFRQ) mode
        TC5->COUNT16.CC[0].reg = 3000 - 1;            // Set the trigger to 16 kHz: (4Mhz / 16000) - 1
        while (TC5->COUNT16.SYNCBUSY.bit.CC0)
            ; // Wait for synchronization
    
        // Start Timer/Counter 5
        TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable the TC5 timer
        while (TC5->COUNT16.SYNCBUSY.bit.ENABLE)
            ; // Wait for synchronization
    }
    
    uint16_t _adc_buf_0[ADC_BUF_LEN];
    uint16_t _adc_buf_1[ADC_BUF_LEN];
    

    Acest cod definește o metodă configureDmaAdc care configurează DMAC, conectându-l la ADC și setându-l să populeze două buffere alternante, _adc_buf_0 și _adc_buf_1.

    💁 Unul dintre dezavantajele dezvoltării pentru microcontrolere este complexitatea codului necesar pentru a interacționa cu hardware-ul, deoarece codul tău rulează la un nivel foarte jos, interacționând direct cu hardware-ul. Acest cod este mai complex decât ceea ce ai scrie pentru un computer cu placă unică sau un computer desktop, deoarece nu există un sistem de operare care să ajute. Există unele biblioteci disponibile care pot simplifica acest lucru, dar tot există multă complexitate.

  7. Mai jos, adaugă următorul cod:

    // WAV files have a header. This struct defines that header
    struct wavFileHeader
    {
        char riff[4];         /* "RIFF"                                  */
        long flength;         /* file length in bytes                    */
        char wave[4];         /* "WAVE"                                  */
        char fmt[4];          /* "fmt "                                  */
        long chunk_size;      /* size of FMT chunk in bytes (usually 16) */
        short format_tag;     /* 1=PCM, 257=Mu-Law, 258=A-Law, 259=ADPCM */
        short num_chans;      /* 1=mono, 2=stereo                        */
        long srate;           /* Sampling rate in samples per second     */
        long bytes_per_sec;   /* bytes per second = srate*bytes_per_samp */
        short bytes_per_samp; /* 2=16-bit mono, 4=16-bit stereo          */
        short bits_per_samp;  /* Number of bits per sample               */
        char data[4];         /* "data"                                  */
        long dlength;         /* data length in bytes (filelength - 44)  */
    };
    
    void initBufferHeader()
    {
        wavFileHeader wavh;
    
        strncpy(wavh.riff, "RIFF", 4);
        strncpy(wavh.wave, "WAVE", 4);
        strncpy(wavh.fmt, "fmt ", 4);
        strncpy(wavh.data, "data", 4);
    
        wavh.chunk_size = 16;
        wavh.format_tag = 1; // PCM
        wavh.num_chans = 1;  // mono
        wavh.srate = RATE;
        wavh.bytes_per_sec = (RATE * 1 * 16 * 1) / 8;
        wavh.bytes_per_samp = 2;
        wavh.bits_per_samp = 16;
        wavh.dlength = RATE * 2 * 1 * 16 / 2;
        wavh.flength = wavh.dlength + 44;
    
        _writer.writeSfudBuffer((byte *)&wavh, 44);
    }
    

    Acest cod definește header-ul WAV ca o structură care ocupă 44 bytes de memorie. Scrie detalii despre rata fișierului audio, dimensiune și numărul de canale. Acest header este apoi scris în memoria flash.

  8. Mai jos de acest cod, adaugă următoarele pentru a declara o metodă care va fi apelată când bufferele audio sunt gata de procesare:

    void audioCallback(uint16_t *buf, uint32_t buf_len)
    {
        static uint32_t idx = 44;
    
        if (_isRecording)
        {
            for (uint32_t i = 0; i < buf_len; i++)
            {
                int16_t audio_value = ((int16_t)buf[i] - 2048) * 16;
    
                _writer.writeSfudBuffer(audio_value & 0xFF);
                _writer.writeSfudBuffer((audio_value >> 8) & 0xFF);
            }
    
            idx += buf_len;
    
            if (idx >= BUFFER_SIZE)
            {
                _writer.flushSfudBuffer();
                idx = 44;
                _isRecording = false;
                _isRecordingReady = true;
            }
        }
    }
    

    Bufferele audio sunt array-uri de întregi pe 16 biți care conțin audio-ul de la ADC. ADC-ul returnează valori nesemnate pe 12 biți (0-1023), astfel încât acestea trebuie convertite în valori semnate pe 16 biți, apoi convertite în 2 bytes pentru a fi stocate ca date binare brute.

    Acești bytes sunt scriși în bufferele de memorie flash. Scrierea începe la indexul 44 - acesta este offset-ul de la cei 44 bytes scriși ca header al fișierului WAV. Odată ce toate bytes-urile necesare pentru lungimea audio-ului dorit au fost capturate, datele rămase sunt scrise în memoria flash.

  9. În secțiunea public a clasei Mic, adaugă următorul cod:

    void dmaHandler()
    {
        static uint8_t count = 0;
    
        if (DMAC->Channel[1].CHINTFLAG.bit.SUSP)
        {
            DMAC->Channel[1].CHCTRLB.reg = DMAC_CHCTRLB_CMD_RESUME;
            DMAC->Channel[1].CHINTFLAG.bit.SUSP = 1;
    
            if (count)
            {
                audioCallback(_adc_buf_0, ADC_BUF_LEN);
            }
            else
            {
                audioCallback(_adc_buf_1, ADC_BUF_LEN);
            }
    
            count = (count + 1) % 2;
        }
    }
    

    Acest cod va fi apelat de DMAC pentru a spune codului tău să proceseze bufferele. Verifică dacă există date de procesat și apelează metoda audioCallback cu bufferul relevant.

  10. În afara clasei, după declarația Mic mic;, adaugă următorul cod:

    void DMAC_1_Handler()
    {
        mic.dmaHandler();
    }
    

    DMAC_1_Handler va fi apelat de DMAC când bufferele sunt gata de procesare. Această funcție este găsită după nume, astfel încât trebuie doar să existe pentru a fi apelată.

  11. Adaugă următoarele două metode în secțiunea public a clasei Mic:

    void init()
    {
        analogReference(AR_INTERNAL2V23);
    
        _writer.init();
    
        initBufferHeader();
        configureDmaAdc();
    }
    
    void reset()
    {
        _isRecordingReady = false;
        _isRecording = false;
    
        _writer.reset();
    
        initBufferHeader();
    }
    

    Metoda init conține cod pentru a inițializa clasa Mic. Această metodă setează tensiunea corectă pentru pinul microfonului, configurează scriitorul de memorie flash, scrie header-ul fișierului WAV și configurează DMAC. Metoda reset resetează memoria flash și rescrie header-ul după ce audio-ul a fost capturat și utilizat.

Sarcină - capturarea audio-ului

  1. În fișierul main.cpp, adaugă o directivă de includere pentru fișierul header mic.h:

    #include "mic.h"
    
  2. În funcția setup, inițializează butonul C. Capturarea audio va începe când acest buton este apăsat și va continua timp de 4 secunde:

    pinMode(WIO_KEY_C, INPUT_PULLUP);
    
  3. Mai jos, inițializează microfonul, apoi afișează în consolă că audio-ul este gata de capturat:

    mic.init();
    
    Serial.println("Ready.");
    
  4. Deasupra funcției loop, definește o funcție pentru a procesa audio-ul capturat. Deocamdată, aceasta nu face nimic, dar mai târziu în această lecție va trimite vorbirea pentru a fi convertită în text:

    void processAudio()
    {
    
    }
    
  5. Adaugă următoarele în funcția loop:

    void loop()
    {
        if (digitalRead(WIO_KEY_C) == LOW && !mic.isRecording())
        {
            Serial.println("Starting recording...");
            mic.startRecording();
        }
    
        if (!mic.isRecording() && mic.isRecordingReady())
        {
            Serial.println("Finished recording");
    
            processAudio();
    
            mic.reset();
        }
    }
    

    Acest cod verifică butonul C, iar dacă acesta este apăsat și înregistrarea nu a început, atunci câmpul _isRecording al clasei Mic este setat la true. Acest lucru va face ca metoda audioCallback a clasei Mic să stocheze audio-ul până când 4 secunde au fost capturate. Odată ce cele 4 secunde de audio au fost capturate, câmpul _isRecording este setat la false, iar câmpul _isRecordingReady este setat la true. Acest lucru este apoi verificat în funcția loop, iar când este true, funcția processAudio este apelată, apoi clasa Mic este resetată.

  6. Construiește acest cod, încarcă-l pe Wio Terminal și testează-l prin monitorul serial. Apasă butonul C (cel din partea stângă, cel mai aproape de comutatorul de alimentare) și vorbește. Vor fi capturate 4 secunde de audio.

    --- Available filters and text transformations: colorize, debug, default, direct, hexlify, log2file, nocontrol, printable, send_on_enter, time
    --- More details at http://bit.ly/pio-monitor-filters
    --- Miniterm on /dev/cu.usbmodem1101  9600,8,N,1 ---
    --- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
    Ready.
    Starting recording...
    Finished recording
    

💁 Puteți găsi acest cod în folderul code-record/wio-terminal. 😀 Programul tău de înregistrare audio a fost un succes!


Declinarea responsabilității:
Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. Deși depunem eforturi pentru a asigura acuratețea, vă rugăm să rețineți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa nativă ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm răspunderea pentru eventualele neînțelegeri sau interpretări greșite care pot apărea din utilizarea acestei traduceri.