25 KiB
Tallenna ääntä - Wio Terminal
Tässä oppitunnin osassa kirjoitat koodia äänen tallentamiseen Wio Terminal -laitteellasi. Äänen tallennusta ohjataan yhdellä Wio Terminalin yläosassa olevista painikkeista.
Ohjelmoi laite tallentamaan ääntä
Voit tallentaa ääntä mikrofonista C++-koodilla. Wio Terminalissa on vain 192KB RAM-muistia, mikä ei riitä tallentamaan kuin muutaman sekunnin ääntä. Siinä on kuitenkin 4MB flash-muistia, jota voidaan käyttää tallentamalla ääni flash-muistiin.
Sisäänrakennettu mikrofoni tallentaa analogisen signaalin, joka muunnetaan digitaaliseksi signaaliksi, jota Wio Terminal voi käyttää. Kun ääntä tallennetaan, tiedot on tallennettava oikeaan aikaan – esimerkiksi 16 kHz:n äänen tallentamiseksi ääni on tallennettava tarkalleen 16 000 kertaa sekunnissa, tasaisin välein jokaisen näytteen välillä. Sen sijaan, että koodisi hoitaisi tämän, voit käyttää suoran muistin pääsyn ohjainta (DMAC). Tämä on piiri, joka voi tallentaa signaalin jostain ja kirjoittaa sen muistiin keskeyttämättä prosessorilla ajettavaa koodiasi.
✅ Lue lisää DMA:sta Wikipedia-artikkelista suorasta muistin pääsystä.
DMAC voi tallentaa ääntä ADC:ltä kiintein välein, esimerkiksi 16 000 kertaa sekunnissa 16 kHz:n ääntä varten. Se voi kirjoittaa nämä tallennetut tiedot ennalta varattuun muistipuskuriin, ja kun tämä on täynnä, se ilmoittaa koodillesi, että puskuri on valmis käsiteltäväksi. Tämän muistin käyttö voi viivästyttää äänen tallennusta, mutta voit asettaa useita puskureita. DMAC kirjoittaa puskuriin 1, ja kun se on täynnä, se ilmoittaa koodillesi käsitellä puskuri 1, samalla kun DMAC kirjoittaa puskuriin 2. Kun puskuri 2 on täynnä, se ilmoittaa koodillesi ja palaa kirjoittamaan puskuriin 1. Näin kauan kuin käsittelet jokaisen puskurin nopeammin kuin sen täyttymiseen kuluva aika, et menetä mitään tietoja.
Kun jokainen puskuri on tallennettu, se voidaan kirjoittaa flash-muistiin. Flash-muistiin on kirjoitettava määritellyillä osoitteilla, jotka määrittävät, mihin kirjoitetaan ja kuinka paljon kirjoitetaan, mikä on samanlaista kuin tavutaulukon päivittäminen muistissa. Flash-muistilla on rakeisuus, mikä tarkoittaa, että tyhjennys- ja kirjoitustoiminnot eivät perustu vain kiinteään kokoon, vaan myös kohdistuvat siihen kokoon. Esimerkiksi, jos rakeisuus on 4096 tavua ja pyydät tyhjennystä osoitteessa 4200, se voi tyhjentää kaikki tiedot osoitteista 4096–8192. Tämä tarkoittaa, että kun kirjoitat äänitiedot flash-muistiin, niiden on oltava oikean kokoisissa paloissa.
Tehtävä - konfiguroi flash-muisti
-
Luo uusi Wio Terminal -projekti PlatformIO:lla. Nimeä tämä projekti
smart-timer
. Lisää koodiasetup
-funktioon sarjaportin konfiguroimiseksi. -
Lisää seuraavat kirjastoriippuvuudet
platformio.ini
-tiedostoon, jotta saat pääsyn flash-muistiin:lib_deps = seeed-studio/Seeed Arduino FS @ 2.1.1 seeed-studio/Seeed Arduino SFUD @ 2.0.2
-
Avaa
main.cpp
-tiedosto ja lisää seuraavainclude
-direktiivi flash-muistikirjastolle tiedoston alkuun:#include <sfud.h> #include <SPI.h>
🎓 SFUD tarkoittaa Serial Flash Universal Driveria, ja se on kirjasto, joka on suunniteltu toimimaan kaikkien flash-muistisirujen kanssa.
-
Lisää
setup
-funktioon seuraava koodi flash-muistikirjaston alustamiseksi:while (!(sfud_init() == SFUD_SUCCESS)) ; sfud_qspi_fast_read_enable(sfud_get_device(SFUD_W25Q32_DEVICE_INDEX), 2);
Tämä silmukoi, kunnes SFUD-kirjasto on alustettu, ja kytkee sitten päälle nopean lukemisen. Sisäänrakennettuun flash-muistiin pääsee Queued Serial Peripheral Interface (QSPI) -liitännän kautta, joka on eräänlainen SPI-ohjain, joka mahdollistaa jatkuvan pääsyn jonon kautta minimaalisella prosessorin käytöllä. Tämä tekee flash-muistin lukemisesta ja kirjoittamisesta nopeampaa.
-
Luo uusi tiedosto
src
-kansioon nimeltäflash_writer.h
. -
Lisää tämän tiedoston alkuun seuraava:
#pragma once #include <Arduino.h> #include <sfud.h>
Tämä sisältää tarvittavat otsikkotiedostot, mukaan lukien SFUD-kirjaston otsikkotiedoston flash-muistin kanssa vuorovaikuttamista varten.
-
Määritä uusi luokka nimeltä
FlashWriter
tässä otsikkotiedostossa:class FlashWriter { public: private: };
-
Lisää
private
-osioon seuraava koodi:byte *_sfudBuffer; size_t _sfudBufferSize; size_t _sfudBufferPos; size_t _sfudBufferWritePos; const sfud_flash *_flash;
Tämä määrittää kenttiä puskurille, jota käytetään tietojen tallentamiseen ennen niiden kirjoittamista flash-muistiin. Siinä on tavutaulukko,
_sfudBuffer
, johon tiedot kirjoitetaan, ja kun tämä on täynnä, tiedot kirjoitetaan flash-muistiin. Kenttä_sfudBufferPos
tallentaa nykyisen sijainnin, johon kirjoitetaan tässä puskurissa, ja_sfudBufferWritePos
tallentaa sijainnin flash-muistissa, johon kirjoitetaan._flash
on osoitin flash-muistiin, johon kirjoitetaan – joissakin mikrokontrollereissa on useita flash-muistisiruja. -
Lisää seuraava metodi
public
-osioon tämän luokan alustamiseksi:void init() { _flash = sfud_get_device_table() + 0; _sfudBufferSize = _flash->chip.erase_gran; _sfudBuffer = new byte[_sfudBufferSize]; _sfudBufferPos = 0; _sfudBufferWritePos = 0; }
Tämä konfiguroi Wio Terminalin flash-muistin kirjoittamista varten ja asettaa puskurit flash-muistin rakeisuuden perusteella. Tämä on
init
-metodissa, eikä konstruktorissa, koska tämä on kutsuttava sen jälkeen, kun flash-muisti on alustettusetup
-funktiossa. -
Lisää seuraava koodi
public
-osioon: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; } }
Tämä koodi määrittää metodit tavujen kirjoittamiseen flash-muistijärjestelmään. Se toimii kirjoittamalla muistipuskuriin, joka on oikean kokoinen flash-muistille, ja kun tämä on täynnä, se kirjoitetaan flash-muistiin, tyhjentäen kaikki olemassa olevat tiedot kyseisestä sijainnista. Mukana on myös
flushSfudBuffer
, joka kirjoittaa epätäydellisen puskurin, koska tallennettavat tiedot eivät ole tarkkoja rakeisuuden monikertoja, joten tiedon loppuosa on kirjoitettava.💁 Tiedon loppuosa kirjoittaa ylimääräisiä ei-toivottuja tietoja, mutta tämä on ok, koska vain tarvittavat tiedot luetaan.
Tehtävä - aseta äänen tallennus
-
Luo uusi tiedosto
src
-kansioon nimeltäconfig.h
. -
Lisää tämän tiedoston alkuun seuraava:
#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
Tämä koodi määrittää joitakin vakioita äänen tallennusta varten.
Vakio Arvo Kuvaus RATE 16000 Äänen näytteenottotaajuus. 16 000 on 16 kHz SAMPLE_LENGTH_SECONDS 4 Tallennettavan äänen pituus sekunteina. Tämä on asetettu 4 sekuntiin. Jos haluat tallentaa pidempään, lisää tätä arvoa. SAMPLES 64000 Tallennettavien ääninäytteiden kokonaismäärä. Asetettu näytteenottotaajuus * sekuntien määrä BUFFER_SIZE 128044 Äänipuskurin koko tallennusta varten. Ääni tallennetaan WAV-tiedostona, jossa on 44 tavun otsikko ja 128 000 tavua äänidataa (jokainen näyte on 2 tavua) ADC_BUF_LEN 1600 Puskureiden koko äänen tallentamiseen DMAC:lla 💁 Jos huomaat, että 4 sekuntia on liian lyhyt ajastimen pyytämiseen, voit kasvattaa
SAMPLE_LENGTH_SECONDS
-arvoa, ja kaikki muut arvot lasketaan uudelleen. -
Luo uusi tiedosto
src
-kansioon nimeltämic.h
. -
Lisää tämän tiedoston alkuun seuraava:
#pragma once #include <Arduino.h> #include "config.h" #include "flash_writer.h"
Tämä sisältää tarvittavat otsikkotiedostot, mukaan lukien
config.h
- jaFlashWriter
-otsikkotiedostot. -
Lisää seuraava määrittääksesi
Mic
-luokan, joka voi tallentaa mikrofonista: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;
Tämä luokka sisältää tällä hetkellä vain muutaman kentän, joilla seurataan, onko tallennus alkanut ja onko tallennus valmis käytettäväksi. Kun DMAC on asetettu, se kirjoittaa jatkuvasti muistipuskureihin, joten
_isRecording
-lippu määrittää, pitäisikö näitä käsitellä vai ohittaa._isRecordingReady
-lippu asetetaan, kun tarvittavat 4 sekuntia ääntä on tallennettu._writer
-kenttää käytetään tallentamaan äänidata flash-muistiin.Globaalimuuttuja määritellään sitten
Mic
-luokan instanssille. -
Lisää seuraava koodi
Mic
-luokanprivate
-osioon: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];
Tämä koodi määrittää
configureDmaAdc
-metodin, joka konfiguroi DMAC:n, yhdistää sen ADC:hen ja asettaa sen täyttämään kaksi vuorottelevaa puskuriä,_adc_buf_0
ja_adc_buf_1
.💁 Yksi mikrokontrollerikehityksen haitoista on monimutkainen koodi, jota tarvitaan laitteiston kanssa vuorovaikuttamiseen, koska koodisi toimii hyvin matalalla tasolla suoraan laitteiston kanssa. Tämä koodi on monimutkaisempaa kuin mitä kirjoittaisit yksikorttitietokoneelle tai pöytätietokoneelle, koska käyttöjärjestelmä ei auta. Joitakin kirjastoja on saatavilla tämän yksinkertaistamiseksi, mutta monimutkaisuutta on silti paljon.
-
Tämän alapuolelle lisää seuraava koodi:
// 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); }
Tämä koodi määrittää WAV-otsikon rakenteena, joka vie 44 tavua muistia. Se kirjoittaa siihen tiedot äänitiedoston taajuudesta, koosta ja kanavien määrästä. Tämä otsikko kirjoitetaan sitten flash-muistiin.
-
Tämän koodin alapuolelle lisää seuraava metodi, joka kutsutaan, kun äänipuskurit ovat valmiita käsiteltäväksi:
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; } } }
Äänipuskurit ovat 16-bittisten kokonaislukujen taulukoita, jotka sisältävät ADC:ltä saadun äänen. ADC palauttaa 12-bittisiä allekirjoittamattomia arvoja (0–1023), joten nämä on muunnettava 16-bittisiksi allekirjoitetuiksi arvoiksi ja sitten muunnettava 2 tavuksi, jotta ne voidaan tallentaa raakana binääridatana.
Nämä tavut kirjoitetaan flash-muistipuskureihin. Kirjoitus alkaa indeksistä 44 – tämä on WAV-tiedoston otsikkona kirjoitettujen 44 tavun siirtymä. Kun kaikki tarvittavat näytteet äänen pituudelle on tallennettu, jäljellä olevat tiedot kirjoitetaan flash-muistiin.
-
Lisää
Mic
-luokanpublic
-osioon seuraava koodi: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; } }
Tämä koodi kutsutaan DMAC:n toimesta, kun puskureita on käsiteltävänä. Se tarkistaa, että käsiteltävää dataa on, ja kutsuu
audioCallback
-metodia oikealla puskurilla. -
Luokan ulkopuolella,
Mic mic;
-määrittelyn jälkeen, lisää seuraava koodi:void DMAC_1_Handler() { mic.dmaHandler(); }
DMAC_1_Handler
kutsutaan DMAC:n toimesta, kun puskureita on valmiina käsiteltäväksi. Tämä funktio löytyy nimen perusteella, joten sen tarvitsee vain olla olemassa, jotta sitä voidaan kutsua. -
Lisää seuraavat kaksi metodia
Mic
-luokanpublic
-osioon:void init() { analogReference(AR_INTERNAL2V23); _writer.init(); initBufferHeader(); configureDmaAdc(); } void reset() { _isRecordingReady = false; _isRecording = false; _writer.reset(); initBufferHeader(); }
init
-metodi sisältää koodinMic
-luokan alustamiseen. Tämä metodi asettaa oikean jännitteen Mic-pinnille, alustaa flash-muistikirjoittimen, kirjoittaa WAV-tiedoston otsikon ja konfiguroi DMAC:n.reset
-metodi nollaa flash-muistin ja kirjoittaa otsikon uudelleen sen jälkeen, kun ääni on tallennettu ja käytetty.
Tehtävä - tallenna ääntä
-
Lisää
main.cpp
-tiedostoonmic.h
-otsikkotiedostoninclude
-direktiivi:#include "mic.h"
-
Lisää
setup
-funktioon C-painikkeen alustaminen. Äänen tallennus alkaa, kun tätä painiketta painetaan, ja jatkuu 4 sekuntia:pinMode(WIO_KEY_C, INPUT_PULLUP);
-
Tämän alapuolelle alusta mikrofoni ja tulosta konsoliin, että ääni on valmis tallennettavaksi:
mic.init(); Serial.println("Ready.");
-
Lisää
loop
-funktion yläpuolelle funktio tallennetun äänen käsittelemiseksi. Tällä hetkellä tämä ei tee mitään, mutta myöhemmin tässä oppitunnissa se lähettää puheen tekstiksi muunnettavaksi:void processAudio() { }
-
Lisää seuraava
loop
-funktioon: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(); } }
Tämä koodi tarkistaa C-painikkeen, ja jos sitä painetaan eikä tallennus ole alkanut,
Mic
-luokan_isRecording
-kenttä asetetaan todeksi. Tämä saaMic
-luokanaudioCallback
-metodin tallentamaan ääntä, kunnes 4 sekuntia on tallennettu. Kun 4 sekuntia ääntä on tallennettu,_isRecording
-kenttä asetetaan epätodeksi ja_isRecordingReady
-kenttä asetetaan todeksi. Tätä tarkistetaanloop
-funktiossa, ja kun se on tosi, kutsutaanprocessAudio
-funktiota ja sittenmic
-luokka nollataan. -
Käännä tämä koodi, lataa se Wio Terminal -laitteeseesi ja testaa se sarjamonitorin kautta. Paina C-painiketta (vasemmalla puolella, lähimpänä virtakytkintä) ja puhu. 4 sekuntia ääntä tallennetaan.
--- 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
💁 Löydät tämän koodin code-record/wio-terminal -kansiosta. 😀 Äänitysohjelmasi oli menestys!
Vastuuvapauslauseke:
Tämä asiakirja on käännetty käyttämällä tekoälypohjaista käännöspalvelua Co-op Translator. Vaikka pyrimme tarkkuuteen, huomioithan, että automaattiset käännökset voivat sisältää virheitä tai epätarkkuuksia. Alkuperäistä asiakirjaa sen alkuperäisellä kielellä tulisi pitää ensisijaisena lähteenä. Kriittisen tiedon osalta suositellaan ammattimaista ihmiskäännöstä. Emme ole vastuussa väärinkäsityksistä tai virhetulkinnoista, jotka johtuvat tämän käännöksen käytöstä.