Äänipiirin AD-muunnin muuntaa mikrofonilta tulevan analogisen signaalin digitaaliseksi
PCM-signaaliksi. Esimerkiksi tyypillisessä CD-laatuisessa äänessä näytteenottotaajuus on 44 100 Hz ja käytössä on 16-bittiset näytteet, eli yhden sekunnin mittaisessa digitaalisessa tallenteessa on 44 100 kpl 16-bittisiä numeroita (0-65535). CD-äänessä on lisäksi kaksi erillistä kanavaa (stereo). Mikrofonilta tulevassa äänessä on tyypillisesti yksi kanava tai monoääni on kahdennettu kahdelle kanavalle.
Mainitsemaasi 100 paikan taulukkoon voi siis tallentaa 2,3 millisekuntia CD-laatuista monoääntä. 44 100 paikan taulukkoon voit tallentaa 1 sekunnin verran ääntä ja 2 646 000 paikan taulukkoon 1 minuutin pätkän. 16-bittisenä sekunnin pätkä tarvitsee muistia tai tallennustilaa 88 200 tavua eli 86 kt ja minuutin pätkään tarvitaan 5 292 000 tavua eli reilut 5 Mt. Tällaisten datamäärien käsittely on nykyisille tietokoneille täysin triviaalia. Esimerkiksi Full HD -näytölle piirrettävän 60 Hz RGB-signaalin datamäärä on yli 4000 kertaa isompi (356 Mt/s), ja sekin on tänä päivänä pientä lämmittelyä, kun erillisten näytönohjainten ja tehokkaimpien prosessorien muistiväylät ovat parhaimmillaan 1000 kertaa nopeampia (työpöytäprosessoreissa 50 Gt/s, uusimmissa näytönohjaimissa 700 Gt/s). Mikrofonin äänisignaalin siirto ja kevyt prosessointi vaatii siis noin miljoonasosan nykyaikaisen tietokoneen laskentakapasiteetista.
Jos haluat esimerkkikoodia äänen kaappaamista varten, ChatGPT, Claude, Gemini ja vastaavat tekoälymallit osaavat opastaa alusta alkaen. Esimerkiksi simppeli C-ohjelma äänen tallentamiseen ALSA-rajapinnan kautta voisi näyttää seuraavalta:
Prompti:
Kirjoita C-kielinen ohjelma äänen kaappaamiseen muistipuskuriin Linuxissa. Toteuta komentorivivalitsin, jolla asetetaan kaapattavan äänen pituus sekunteina. Käytä lähdekoodissa englanninkielisiä tekstejä ja kommentteja.
Tekoälyn kirjoittama koodi capture.c:
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#define SAMPLE_RATE 44100
#define CHANNELS 1
#define FORMAT SND_PCM_FORMAT_S16_LE
int main(int argc, char *argv[]) {
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
int err;
// Default capture time = 1 second
int seconds = 1;
// Parse command-line argument
if (argc > 1) {
seconds = atoi(argv[1]);
if (seconds <= 0) {
fprintf(stderr, "Invalid duration: %s\n", argv[1]);
return 1;
}
}
printf("Capturing %d second(s) of audio...\n", seconds);
// Open default capture device
if ((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0) {
fprintf(stderr, "Unable to open PCM device: %s\n", snd_strerror(err));
return 1;
}
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle, params);
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, params, FORMAT);
snd_pcm_hw_params_set_channels(handle, params, CHANNELS);
snd_pcm_hw_params_set_rate(handle, params, SAMPLE_RATE, 0);
if ((err = snd_pcm_hw_params(handle, params)) < 0) {
fprintf(stderr, "Unable to set HW params: %s\n", snd_strerror(err));
snd_pcm_close(handle);
return 1;
}
// Calculate total samples & buffer size
size_t bytes_per_sample = 2; // S16_LE = 2 bytes
size_t total_samples = (size_t)SAMPLE_RATE * CHANNELS * seconds;
size_t buffer_size = total_samples * bytes_per_sample;
unsigned char *buffer = malloc(buffer_size);
if (!buffer) {
fprintf(stderr, "Memory allocation failed\n");
snd_pcm_close(handle);
return 1;
}
size_t frames_to_read = SAMPLE_RATE * seconds;
// Capture audio
ssize_t frames_read = snd_pcm_readi(handle, buffer, frames_to_read);
if (frames_read < 0) {
fprintf(stderr, "Read error: %s\n", snd_strerror(frames_read));
snd_pcm_close(handle);
free(buffer);
return 1;
}
printf("Captured %zd frames (%zu bytes) into memory.\n",
frames_read, buffer_size);
snd_pcm_close(handle);
free(buffer);
return 0;
}
Asenna ALSA:n headerit eli libasound2-dev:
sudo apt install libasound2-devKäännä:
gcc capture.c -lasound -o captureSuorita:
./capture 5