⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snd.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
字号:
/* snd.c -- low-level sound I/O * * Roger Dannenberg * 21 Jun 1997 * * based on sndheader.c: * * Jim Zelenka, CMU/ITC, 9 Jun 1992 (rewritten from my old sources) * Roger Dannenberg, CMU, Mar 1993 (extensive changes and additions) * * and on sndread.c & sndwrite.c: * * Roger Dannenberg *//* Standard includes */#include <string.h>#include <stdio.h>#include "snd.h"#include "sndfileio.h"#include "sndheader.h"static int snd_initialized = FALSE;typedef struct {    char *interf;    char *device;    snd_fns_type dictionary;} descriptor_node, *descriptor_type;static int descriptor_index = 0;#define snd_descriptor_max 32static descriptor_node descriptors[snd_descriptor_max];/* snd_add_device -- describe interface/device pair to library  * * This is called at intialization time, once for each  * interface (e.g. DirectSound) and device (e.g. SoundBlaster 1) * The strings are retained but NOT COPIED, so do not destroy them! */void snd_add_device(char *interf, char *device, snd_fns_type dictionary){    if (descriptor_index >= snd_descriptor_max) {        snd_fail("snd_add_device: snd_descriptor_max exceeded");    }    descriptors[descriptor_index].interf = interf;    descriptors[descriptor_index].device = device;    descriptors[descriptor_index].dictionary = dictionary;    descriptor_index++;}    int snd_device(int n, char *interf, char *device){    if (!snd_initialized) {        snd_init();        snd_initialized = TRUE;    }    if (n >= 0 && n < descriptor_index) {        strcpy(interf, descriptors[n].interf);        strcpy(device, descriptors[n].device);        return SND_SUCCESS;    }    return !SND_SUCCESS;}/* failure_fn -- "noop" function pointer *//**/static int failure_fn(snd_type snd){    return !SND_SUCCESS;}/* success_fn -- "noop" function pointer *//**/static int success_fn(snd_type snd){    return SND_SUCCESS;}static long file_poll(snd_type snd){    return MAX_FILE_BUF_LEN;}static long mem_poll(snd_type snd){    if (snd->write_flag == SND_READ) {        return (snd->u.mem.buffer_len - snd->u.mem.buffer_pos);    } else {        return (snd->u.mem.buffer_max - snd->u.mem.buffer_len);    }}static long none_poll(snd_type snd){    return 0;}#if !defined(WIN32) && !defined(IRIX) && !defined(SGI)static void _swab(char *to, char *from, long length){    short *to16 = (short *) to;    short *from16 = (short *) from;    int i = 1;    while (i < length) {        short data = *from16++;        *to16++ = (data << 8) | ((data >> 8) & 0xFF);        i += 2;    }}#endifstatic void change_byte_order(snd_type snd, void *buffer, long length){    int bytes = (snd->format.bits + 7) >> 3;    switch (bytes) {      case 1:        break;      case 2:        _swab((char *) buffer, (char *) buffer, length);        break;      case 4: {        long *buff = (long *) buffer;        while (length > 0) {            long data = *buff;            *buff++ = ((data >> 24) & 0xFF) | ((data >> 8) & 0xFF00) |                ((data << 8) & 0xFF0000) | (data << 24);            length -= 4;        }        break;      }      default: {        char msg[100];        sprintf(msg, "Cannot handle %d-byte samples", bytes);        snd_fail(msg);        break;      }    }}static long file_read(snd_type snd, void *buffer, long length){    long togo, cnt;    togo = snd->u.file.end_offset - snd->u.file.current_offset;    if (length > togo) length = togo;    cnt = snd_file_read(snd->u.file.file, (char *) buffer, length);    snd->u.file.current_offset += cnt;    if (snd->u.file.swap) change_byte_order(snd, buffer, cnt);    return cnt;}      static long mem_read(snd_type snd, void *buffer, long length){    /* if there are fewer than length bytes, reduce length: */    if ((snd->u.mem.buffer_len - snd->u.mem.buffer_pos) < length) {        length = snd->u.mem.buffer_len - snd->u.mem.buffer_pos;    }    memcpy(buffer, snd->u.mem.buffer + snd->u.mem.buffer_pos,            length);    snd->u.mem.buffer_pos += length;    return length;}static long none_read(snd_type snd, void *buffer, long length){    return 0;}static long file_write(snd_type snd, void *buffer, long length){    long cnt;    if (snd->u.file.swap) change_byte_order(snd, buffer, length);    cnt = snd_file_write(snd->u.file.file, (char *) buffer, length);    snd->u.file.end_offset += cnt;	/* keep track of how much data */    return cnt;}    static long mem_write(snd_type snd, void *buffer, long length){    /* if there are fewer than length bytes, reduce length: */    if ((snd->u.mem.buffer_max - snd->u.mem.buffer_len) < length) {        length = snd->u.mem.buffer_max - snd->u.mem.buffer_len;    }    memcpy(snd->u.mem.buffer + snd->u.mem.buffer_len, buffer, length);    snd->u.mem.buffer_len += length;    return length;}static long none_write(snd_type snd, void *buffer, long length){    return 0;}static int mem_open(snd_type snd, long *flags){    return SND_SUCCESS;}static int none_open(snd_type snd, long *flags){    return !SND_SUCCESS;}static int file_close(snd_type snd){    if (snd->write_flag == SND_WRITE) {        write_sndheader_finish(snd);    }    return snd_file_close(snd->u.file.file);}#define mem_close success_fn#define none_close failure_fn#define file_reset success_fnstatic int mem_reset(snd_type snd){    snd->u.mem.buffer_pos = 0;    if (snd->write_flag != SND_READ) {        snd->u.mem.buffer_len = 0;    }    return SND_SUCCESS;}#define none_reset failure_fn#define file_flush success_fn#define mem_flush success_fn#define none_flush failure_fnchar *snd_mode_string[] = { "ADPCM", "PCM", "ULAW", "ALAW", "Float", "UPCM", "Unknown" };char *snd_mode_to_string(long mode){    if (mode < 0 || mode >= SND_NUM_MODES) return "InvalidData";    else return snd_mode_string[mode];}static snd_fns_node mem_dictionary = {     mem_poll, mem_read, mem_write, mem_open,    mem_close, mem_reset, mem_flush };static snd_fns_node file_dictionary = {    file_poll, file_read, file_write, snd_open_file,        file_close, file_reset, file_flush };snd_fns_node snd_none_dictionary = {    none_poll, none_read, none_write, none_open,        none_close, none_reset, none_flush };long snd_poll(snd_type snd){    return (*snd->dictionary->poll)(snd);}/* snd_read -- read up to length bytes from source into buffer *//* * returns number of bytes actually read */long snd_read(snd_type snd, void *buffer, long length){    int bpf = snd_bytes_per_frame(snd);    return ((*snd->dictionary->read)(snd, buffer, length * bpf)) / bpf;}long snd_write(snd_type snd, void *buffer, long length){    int bpf = snd_bytes_per_frame(snd);    return (*snd->dictionary->write)(snd, buffer, length * bpf) / bpf;}int snd_open(snd_type snd, long *flags){    if (!snd_initialized) {        snd_init();        snd_initialized = TRUE;    }    *flags = 0;    if (snd->device == SND_DEVICE_FILE) {        snd->dictionary = &file_dictionary;    } else if (snd->device == SND_DEVICE_AUDIO) {        int i;        for (i = 0; i < descriptor_index; i++) {            /* take the first descriptor that matches both interface                and device, where empty string matches anything: */            if ((snd->u.audio.interfacename[0] == 0 ||                 strcmp(snd->u.audio.interfacename,                         descriptors[i].interf) == 0) &&                                /*&& commented out by dmazzoni - don't want to compare dev                   && uncommented by rbd - please see previous comment/specification */                (snd->u.audio.devicename[0] == 0 ||                 strcmp(snd->u.audio.devicename,                                  descriptors[i].device) == 0)) {                snd->dictionary = descriptors[i].dictionary;                break;            }        }        if (i >= descriptor_index) {            return !SND_SUCCESS;        }    } else if (snd->device == SND_DEVICE_MEM) {        snd->dictionary = &mem_dictionary;    }    return (*snd->dictionary->open)(snd, flags);}int snd_close(snd_type snd){    return (*snd->dictionary->close)(snd);}int snd_reset(snd_type snd){    return (*snd->dictionary->reset)(snd);}/* snd_flush -- allows client to finish audio output before closing *//**/int snd_flush(snd_type snd){    if (snd->write_flag != SND_READ) {        return (*snd->dictionary->flush)(snd);    }    return SND_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -