linuxALSA应用编程笔记

Posted 守护安静星空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linuxALSA应用编程笔记相关的知识,希望对你有一定的参考价值。

        ALSA是linux的主流音频软件架构,包括驱动和应用程序两个部分,根据官网和自己查找的资料总结了一些知识,更详细的资料参考alsa官网。

        alsa c开发参考文档地址:ALSA project - the C library reference: Index, Preamble and License

ALSA 官方 Examples主要有:

在使用例子之前需要安装ALSA库,Ubuntu开发安装方法:

  1. 进入ALSA主页:AlsaProject Download alsa-lib库解压出来
  2. 编译alsa-lib库 生成makefile ./configure,编译文件 make
  3. 安装alsa库 sudo make install (注意使用sudo超级权限)
  4. 编译例子使用(gcc -o 文件名 文件名.c -lasound)命令

ALSA在linux中的架构图 

示例1 pcm.c创建一个正弦波输入到声卡里面,提供了几种写的方式

struct transfer_method 
    const char *name;
    snd_pcm_access_t access;
    int (*transfer_loop)(snd_pcm_t *handle,
                 signed short *samples,
                 snd_pcm_channel_area_t *areas);
;
 
static struct transfer_method transfer_methods[] = 
     "write", SND_PCM_ACCESS_RW_INTERLEAVED, write_loop ,
     "write_and_poll", SND_PCM_ACCESS_RW_INTERLEAVED, write_and_poll_loop ,
     "async", SND_PCM_ACCESS_RW_INTERLEAVED, async_loop ,
     "async_direct", SND_PCM_ACCESS_MMAP_INTERLEAVED, async_direct_loop ,
     "direct_interleaved", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_loop ,
     "direct_noninterleaved", SND_PCM_ACCESS_MMAP_NONINTERLEAVED, direct_loop ,
     "direct_write", SND_PCM_ACCESS_MMAP_INTERLEAVED, direct_write_loop ,
     NULL, SND_PCM_ACCESS_RW_INTERLEAVED, NULL 
;

        这个文件提供了几个具体写音频数据格式的函数,播放音乐可以使用这些接口具体参考pcm.c文件

播放声音参考pcm_min.c文件:

/*
 *  This extra small demo sends a random samples to your speakers.
 */
 
#include "../include/asoundlib.h"
 
static char *device = "default";            /* playback device */
unsigned char buffer[16*1024];              /* some random data */
 
int main(void)

    int err;
    unsigned int i;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;
 
    for (i = 0; i < sizeof(buffer); i++)
        buffer[i] = random() & 0xff;
 
    if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) 
        printf("Playback open error: %s\\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    
    if ((err = snd_pcm_set_params(handle,
                      SND_PCM_FORMAT_U8,
                      SND_PCM_ACCESS_RW_INTERLEAVED,
                      1,
                      48000,
                      1,
                      500000)) < 0)    /* 0.5sec */
        printf("Playback open error: %s\\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    
 
        for (i = 0; i < 16; i++) 
        frames = snd_pcm_writei(handle, buffer, sizeof(buffer));
        if (frames < 0)
            frames = snd_pcm_recover(handle, frames, 0);
        if (frames < 0) 
            printf("snd_pcm_writei failed: %s\\n", snd_strerror(frames));
            break;
        
        if (frames > 0 && frames < (long)sizeof(buffer))
            printf("Short write (expected %li, wrote %li)\\n", (long)sizeof(buffer), frames);
    
 
    /* pass the remaining samples, otherwise they're dropped in close */
    err = snd_pcm_drain(handle);
    if (err < 0)
        printf("snd_pcm_drain failed: %s\\n", snd_strerror(err));
    snd_pcm_close(handle);
    return 0;

编译此文件: gcc -o pcm_min pcm_min.c -lasound -lm

执行文件:./pcm_min

        这个文件产生一个随机噪声,写到声卡buffer里面播放声音。

录制声音参考 latency.c 

/*
 *  Latency test program
 *
 *     Author: Jaroslav Kysela <perex@perex.cz>
 *
 *     Author of bandpass filter sweep effect:
 *         Maarten de Boer <mdeboer@iua.upf.es>
 *
 *  This small demo program can be used for measuring latency between
 *  capture and playback. This latency is measured from driver (diff when
 *  playback and capture was started). Scheduler is set to SCHED_RR.
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include "../include/asoundlib.h"
#include <sys/time.h>
#include <math.h>
 
char *pdevice = "hw:0,0";
char *cdevice = "hw:0,0";
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
int rate = 22050;
int channels = 2;
int buffer_size = 0;        /* auto */
int period_size = 0;        /* auto */
int latency_min = 32;       /* in frames / 2 */
int latency_max = 2048;     /* in frames / 2 */
int loop_sec = 30;      /* seconds */
int block = 0;          /* block mode */
int use_poll = 0;
int resample = 1;
unsigned long loop_limit;
 
snd_output_t *output = NULL;
 
int setparams_stream(snd_pcm_t *handle,
             snd_pcm_hw_params_t *params,
             const char *id)

    int err;
    unsigned int rrate;
 
    err = snd_pcm_hw_params_any(handle, params);
    if (err < 0) 
        printf("Broken configuration for %s PCM: no configurations available: %s\\n", snd_strerror(err), id);
        return err;
    
    err = snd_pcm_hw_params_set_rate_resample(handle, params, resample);
    if (err < 0) 
        printf("Resample setup failed for %s (val %i): %s\\n", id, resample, snd_strerror(err));
        return err;
    
    err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (err < 0) 
        printf("Access type not available for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    err = snd_pcm_hw_params_set_format(handle, params, format);
    if (err < 0) 
        printf("Sample format not available for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    err = snd_pcm_hw_params_set_channels(handle, params, channels);
    if (err < 0) 
        printf("Channels count (%i) not available for %s: %s\\n", channels, id, snd_strerror(err));
        return err;
    
    rrate = rate;
    err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
    if (err < 0) 
        printf("Rate %iHz not available for %s: %s\\n", rate, id, snd_strerror(err));
        return err;
    
    if ((int)rrate != rate) 
        printf("Rate doesn't match (requested %iHz, get %iHz)\\n", rate, err);
        return -EINVAL;
    
    return 0;

 
int setparams_bufsize(snd_pcm_t *handle,
              snd_pcm_hw_params_t *params,
              snd_pcm_hw_params_t *tparams,
              snd_pcm_uframes_t bufsize,
              const char *id)

    int err;
    snd_pcm_uframes_t periodsize;
 
    snd_pcm_hw_params_copy(params, tparams);
    periodsize = bufsize * 2;
    err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &periodsize);
    if (err < 0) 
        printf("Unable to set buffer size %li for %s: %s\\n", bufsize * 2, id, snd_strerror(err));
        return err;
    
    if (period_size > 0)
        periodsize = period_size;
    else
        periodsize /= 2;
    err = snd_pcm_hw_params_set_period_size_near(handle, params, &periodsize, 0);
    if (err < 0) 
        printf("Unable to set period size %li for %s: %s\\n", periodsize, id, snd_strerror(err));
        return err;
    
    return 0;

 
int setparams_set(snd_pcm_t *handle,
          snd_pcm_hw_params_t *params,
          snd_pcm_sw_params_t *swparams,
          const char *id)

    int err;
    snd_pcm_uframes_t val;
 
    err = snd_pcm_hw_params(handle, params);
    if (err < 0) 
        printf("Unable to set hw params for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    err = snd_pcm_sw_params_current(handle, swparams);
    if (err < 0) 
        printf("Unable to determine current swparams for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0x7fffffff);
    if (err < 0) 
        printf("Unable to set start threshold mode for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    if (!block)
        val = 4;
    else
        snd_pcm_hw_params_get_period_size(params, &val, NULL);
    err = snd_pcm_sw_params_set_avail_min(handle, swparams, val);
    if (err < 0) 
        printf("Unable to set avail min for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    err = snd_pcm_sw_params(handle, swparams);
    if (err < 0) 
        printf("Unable to set sw params for %s: %s\\n", id, snd_strerror(err));
        return err;
    
    return 0;

//设定软件硬件参数 
int setparams(snd_pcm_t *phandle, snd_pcm_t *chandle, int *bufsize)

    int err, last_bufsize = *bufsize;
    snd_pcm_hw_params_t *pt_params, *ct_params; /* templates with rate, format and channels */
    snd_pcm_hw_params_t *p_params, *c_params;
    snd_pcm_sw_params_t *p_swparams, *c_swparams;
    snd_pcm_uframes_t p_size, c_size, p_psize, c_psize;
    unsigned int p_time, c_time;
    unsigned int val;
 
    snd_pcm_hw_params_alloca(&p_params);
    snd_pcm_hw_params_alloca(&c_params);
    snd_pcm_hw_params_alloca(&pt_params);
    snd_pcm_hw_params_alloca(&ct_params);
    snd_pcm_sw_params_alloca(&p_swparams);
    snd_pcm_sw_params_alloca(&c_swparams);
    if ((err = setparams_stream(phandle, pt_params, "playback")) < 0) 
        printf("Unable to set parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
    if ((err = setparams_stream(chandle, ct_params, "capture")) < 0) 
        printf("Unable to set parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
 
    if (buffer_size > 0) 
        *bufsize = buffer_size;
        goto __set_it;
    
 
      __again:
        if (buffer_size > 0)
            return -1;
        if (last_bufsize == *bufsize)
        *bufsize += 4;
    last_bufsize = *bufsize;
    if (*bufsize > latency_max)
        return -1;
      __set_it:
    if ((err = setparams_bufsize(phandle, p_params, pt_params, *bufsize, "playback")) < 0) 
        printf("Unable to set sw parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
    if ((err = setparams_bufsize(chandle, c_params, ct_params, *bufsize, "capture")) < 0) 
        printf("Unable to set sw parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
 
    snd_pcm_hw_params_get_period_size(p_params, &p_psize, NULL);
    if (p_psize > (unsigned int)*bufsize)
        *bufsize = p_psize;
    snd_pcm_hw_params_get_period_size(c_params, &c_psize, NULL);
    if (c_psize > (unsigned int)*bufsize)
        *bufsize = c_psize;
    snd_pcm_hw_params_get_period_time(p_params, &p_time, NULL);
    snd_pcm_hw_params_get_period_time(c_params, &c_time, NULL);
    if (p_time != c_time)
        goto __again;
 
    snd_pcm_hw_params_get_buffer_size(p_params, &p_size);
    if (p_psize * 2 < p_size) 
                snd_pcm_hw_params_get_periods_min(p_params, &val, NULL);
                if (val > 2) 
            printf("playback device does not support 2 periods per buffer\\n");
            exit(0);
        
        goto __again;
    
    snd_pcm_hw_params_get_buffer_size(c_params, &c_size);
    if (c_psize * 2 < c_size) 
                snd_pcm_hw_params_get_periods_min(c_params, &val, NULL);
        if (val > 2 ) 
            printf("capture device does not support 2 periods per buffer\\n");
            exit(0);
        
        goto __again;
    
    if ((err = setparams_set(phandle, p_params, p_swparams, "playback")) < 0) 
        printf("Unable to set sw parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
    if ((err = setparams_set(chandle, c_params, c_swparams, "capture")) < 0) 
        printf("Unable to set sw parameters for playback stream: %s\\n", snd_strerror(err));
        exit(0);
    
 
    if ((err = snd_pcm_prepare(phandle)) < 0) 
        printf("Prepare error: %s\\n", snd_strerror(err));
        exit(0);
    
 
    snd_pcm_dump(phandle, output);
    snd_pcm_dump(chandle, output);
    fflush(stdout);
    return 0;

 
void showstat(snd_pcm_t *handle, size_t frames)

    int err;
    snd_pcm_status_t *status;
 
    snd_pcm_status_alloca(&status);
    if ((err = snd_pcm_status(handle, status)) < 0) 
        printf("Stream status error: %s\\n", snd_strerror(err));
        exit(0);
    
    printf("*** frames = %li ***\\n", (long)frames);
    snd_pcm_status_dump(status, output);

 
void showlatency(size_t latency)

    double d;
    latency *= 2;
    d = (double)latency / (double)rate;
    printf("Trying latency %li frames, %.3fus, %.6fms (%.4fHz)\\n", (long)latency, d * 1000000, d * 1000, (double)1 / d);

 
void showinmax(size_t in_max)

    double d;
 
    printf("Maximum read: %li frames\\n", (long)in_max);
    d = (double)in_max / (double)rate;
    printf("Maximum read latency: %.3fus, %.6fms (%.4fHz)\\n", d * 1000000, d * 1000, (double)1 / d);

 
void gettimestamp(snd_pcm_t *handle, snd_timestamp_t *timestamp)

    int err;
    snd_pcm_status_t *status;
 
    snd_pcm_status_alloca(&status);
    if ((err = snd_pcm_status(handle, status)) < 0) 
        printf("Stream status error: %s\\n", snd_strerror(err));
        exit(0);
    
    snd_pcm_status_get_trigger_tstamp(status, timestamp);

 
void setscheduler(void)

    struct sched_param sched_param;
 
    if (sched_getparam(0, &sched_param) < 0) 
        printf("Scheduler getparam failed...\\n");
        return;
    
    sched_param.sched_priority = sched_get_priority_max(SCHED_RR);
    if (!sched_setscheduler(0, SCHED_RR, &sched_param)) 
        printf("Scheduler set to Round Robin with priority %i...\\n", sched_param.sched_priority);
        fflush(stdout);
        return;
    
    printf("!!!Scheduler set to Round Robin with priority %i FAILED!!!\\n", sched_param.sched_priority);

 
long timediff(snd_timestamp_t t1, snd_timestamp_t t2)

    signed long l;
 
    t1.tv_sec -= t2.tv_sec;
    l = (signed long) t1.tv_usec - (signed long) t2.tv_usec;
    if (l < 0) 
        t1.tv_sec--;
        l = 1000000 + l;
        l %= 1000000;
    
    return (t1.tv_sec * 1000000) + l;

 
long readbuf(snd_pcm_t *handle, char *buf, long len, size_t *frames, size_t *max)

    long r;
 
    if (!block) 
        do 
            r = snd_pcm_readi(handle, buf, len);
         while (r == -EAGAIN);
        if (r > 0) 
            *frames += r;
            if ((long)*max < r)
                *max = r;
        
        // printf("read = %li\\n", r);
     else 
        int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
        do 
            r = snd_pcm_readi(handle, buf, len);
            if (r > 0) 
                buf += r * frame_bytes;
                len -= r;
                *frames += r;
                if ((long)*max < r)
                    *max = r;
            
            // printf("r = %li, len = %li\\n", r, len);
         while (r >= 1 && len > 0);
    
    // showstat(handle, 0);
    return r;

 
long writebuf(snd_pcm_t *handle, char *buf, long len, size_t *frames)

    long r;
    int frame_bytes = (snd_pcm_format_width(format) / 8) * channels;
 
    while (len > 0) 
        r = snd_pcm_writei(handle, buf, len);
        if (r == -EAGAIN)
            continue;
        // printf("write = %li\\n", r);
        if (r < 0)
            return r;
        // showstat(handle, 0);
        buf += r * frame_bytes;
        len -= r;
        *frames += r;
    
    return 0;

            
#define FILTERSWEEP_LFO_CENTER 2000.
#define FILTERSWEEP_LFO_DEPTH 1800.
#define FILTERSWEEP_LFO_FREQ 0.2
#define FILTER_BANDWIDTH 50
 
/* filter the sweep variables */
float lfo,dlfo,fs,fc,BW,C,D,a0,a1,a2,b1,b2,*x[3],*y[3];
 
void applyeffect(char* buffer,int r)

    short* samples = (short*) buffer;
    int i;
    for (i=0;i<r;i++)
    
        int chn;
 
        fc = sin(lfo)*FILTERSWEEP_LFO_DEPTH+FILTERSWEEP_LFO_CENTER;
        lfo += dlfo;
        if (lfo>2.*M_PI) lfo -= 2.*M_PI;
        C = 1./tan(M_PI*BW/fs);
        D = 2.*cos(2*M_PI*fc/fs);
        a0 = 1./(1.+C);
        a1 = 0;
        a2 = -a0;
        b1 = -C*D*a0;
        b2 = (C-1)*a0;
 
        for (chn=0;chn<channels;chn++)
        
            x[chn][2] = x[chn][1];
            x[chn][1] = x[chn][0];
 
            y[chn][2] = y[chn][1];
            y[chn][1] = y[chn][0];
 
            x[chn][0] = samples[i*channels+chn];
            y[chn][0] = a0*x[chn][0] + a1*x[chn][1] + a2*x[chn][2] 
                - b1*y[chn][1] - b2*y[chn][2];
            samples[i*channels+chn] = y[chn][0];
        
    

 
void help(void)

    int k;
    printf(
"Usage: latency [OPTION]... [FILE]...\\n"
"-h,--help      help\\n"
"-P,--pdevice   playback device\\n"
"-C,--cdevice   capture device\\n"
"-m,--min       minimum latency in frames\\n"
"-M,--max       maximum latency in frames\\n"
"-F,--frames    frames to transfer\\n"
"-f,--format    sample format\\n"
"-c,--channels  channels\\n"
"-r,--rate      rate\\n"
"-B,--buffer    buffer size in frames\\n"
"-E,--period    period size in frames\\n"
"-s,--seconds   duration of test in seconds\\n"
"-b,--block     block mode\\n"
"-p,--poll      use poll (wait for event - reduces CPU usage)\\n"
"-e,--effect    apply an effect (bandpass filter sweep)\\n"
);
        printf("Recognized sample formats are:");
        for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) 
                const char *s = snd_pcm_format_name(k);
                if (s)
                        printf(" %s", s);
        
        printf("\\n\\n");
        printf(
"Tip #1 (usable latency with large periods, non-blocking mode, good CPU usage,\\n"
"        superb xrun prevention):\\n"
"  latency -m 8192 -M 8192 -t 1 -p\\n"
"Tip #2 (superb latency, non-blocking mode, but heavy CPU usage):\\n"
"  latency -m 128 -M 128\\n"
);

 
int main(int argc, char *argv[])

    struct option long_option[] =
    
        "help", 0, NULL, 'h',
        "pdevice", 1, NULL, 'P',
        "cdevice", 1, NULL, 'C',
        "min", 1, NULL, 'm',
        "max", 1, NULL, 'M',
        "frames", 1, NULL, 'F',
        "format", 1, NULL, 'f',
        "channels", 1, NULL, 'c',
        "rate", 1, NULL, 'r',
        "buffer", 1, NULL, 'B',
        "period", 1, NULL, 'E',
        "seconds", 1, NULL, 's',
        "block", 0, NULL, 'b',
        "poll", 0, NULL, 'p',
        "effect", 0, NULL, 'e',
        NULL, 0, NULL, 0,
    ;
    snd_pcm_t *phandle, *chandle;
    char *buffer;
    int err, latency, morehelp;
    int ok;
    snd_timestamp_t p_tstamp, c_tstamp;
    ssize_t r;
    size_t frames_in, frames_out, in_max;
    int effect = 0;
    morehelp = 0;
    while (1) 
        int c;
        if ((c = getopt_long(argc, argv, "hP:C:m:M:F:f:c:r:B:E:s:bpen", long_option, NULL)) < 0)
            break;
        switch (c) 
        case 'h':
            morehelp++;
            break;
        case 'P':
            pdevice = strdup(optarg);
            break;
        case 'C':
            cdevice = strdup(optarg);
            break;
        case 'm':
            err = atoi(optarg) / 2;
            latency_min = err >= 4 ? err : 4;
            if (latency_max < latency_min)
                latency_max = latency_min;
            break;
        case 'M':
            err = atoi(optarg) / 2;
            latency_max = latency_min > err ? latency_min : err;
            break;
        case 'f':
            format = snd_pcm_format_value(optarg);
            if (format == SND_PCM_FORMAT_UNKNOWN) 
                printf("Unknown format, setting to default S16_LE\\n");
                format = SND_PCM_FORMAT_S16_LE;
            
            break;
        case 'c':
            err = atoi(optarg);
            channels = err >= 1 && err < 1024 ? err : 1;
            break;
        case 'r':
            err = atoi(optarg);
            rate = err >= 4000 && err < 200000 ? err : 44100;
            break;
        case 'B':
            err = atoi(optarg);
            buffer_size = err >= 32 && err < 200000 ? err : 0;
            break;
        case 'E':
            err = atoi(optarg);
            period_size = err >= 32 && err < 200000 ? err : 0;
            break;
        case 's':
            err = atoi(optarg);
            loop_sec = err >= 1 && err <= 100000 ? err : 30;
            break;
        case 'b':
            block = 1;
            break;
        case 'p':
            use_poll = 1;
            break;
        case 'e':
            effect = 1;
            break;
        case 'n':
            resample = 0;
            break;
        
    
 
    if (morehelp) 
        help();
        return 0;
    
	
	//把输出重定向到stdout
    err = snd_output_stdio_attach(&output, stdout, 0);
    if (err < 0) 
        printf("Output failed: %s\\n", snd_strerror(err));
        return 0;
    
 
    loop_limit = loop_sec * rate;
    latency = latency_min - 4;
    buffer = malloc((latency_max * snd_pcm_format_width(format) / 8) * 2);
	//设定进程调度相关
    setscheduler();
 
    printf("Playback device is %s\\n", pdevice);
    printf("Capture device is %s\\n", cdevice);
    printf("Parameters are %iHz, %s, %i channels, %s mode\\n", rate, snd_pcm_format_name(format), channels, block ? "blocking" : "non-blocking");
    printf("Poll mode: %s\\n", use_poll ? "yes" : "no");
    printf("Loop limit is %lu frames, minimum latency = %i, maximum latency = %i\\n", loop_limit, latency_min * 2, latency_max * 2);
	//打开播放设备
    if ((err = snd_pcm_open(&phandle, pdevice, SND_PCM_STREAM_PLAYBACK, block ? 0 : SND_PCM_NONBLOCK)) < 0) 
        printf("Playback open error: %s\\n", snd_strerror(err));
        return 0;
    
	//打开录音设备
    if ((err = snd_pcm_open(&chandle, cdevice, SND_PCM_STREAM_CAPTURE, block ? 0 : SND_PCM_NONBLOCK)) < 0) 
        printf("Record open error: %s\\n", snd_strerror(err));
        return 0;
    
 
    /* initialize the filter sweep variables */
    if (effect) 
        fs = (float) rate;
        BW = FILTER_BANDWIDTH;
 
        lfo = 0;
        dlfo = 2.*M_PI*FILTERSWEEP_LFO_FREQ/fs;
 
        x[0] = (float*) malloc(channels*sizeof(float));     
        x[1] = (float*) malloc(channels*sizeof(float));     
        x[2] = (float*) malloc(channels*sizeof(float));     
        y[0] = (float*) malloc(channels*sizeof(float));     
        y[1] = (float*) malloc(channels*sizeof(float));     
        y[2] = (float*) malloc(channels*sizeof(float));     
    
              
    while (1) 
        frames_in = frames_out = 0;
        if (setparams(phandle, chandle, &latency) < 0)
            break;
        showlatency(latency);
        if ((err = snd_pcm_link(chandle, phandle)) < 0) 
            printf("Streams link error: %s\\n", snd_strerror(err));
            exit(0);
        
        if (snd_pcm_format_set_silence(format, buffer, latency*channels) < 0) 
            fprintf(stderr, "silence error\\n");
            break;
        
        if (writebuf(phandle, buffer, latency, &frames_out) < 0) 
            fprintf(stderr, "write error\\n");
            break;
        
        if (writebuf(phandle, buffer, latency, &frames_out) < 0) 
            fprintf(stderr, "write error\\n");
            break;
        
 
        if ((err = snd_pcm_start(chandle)) < 0) 
            printf("Go error: %s\\n", snd_strerror(err));
            exit(0);
        
        gettimestamp(phandle, &p_tstamp);
        gettimestamp(chandle, &c_tstamp);
#if 0
        printf("Playback:\\n");
        showstat(phandle, frames_out);
        printf("Capture:\\n");
        showstat(chandle, frames_in);
#endif
 
        ok = 1;
        in_max = 0;
        while (ok && frames_in < loop_limit) 
            if (use_poll) 
                /* use poll to wait for next event */
                snd_pcm_wait(chandle, 1000);
            
            if ((r = readbuf(chandle, buffer, latency, &frames_in, &in_max)) < 0)
                ok = 0;
            else 
                if (effect)
                    applyeffect(buffer,r);
                if (writebuf(phandle, buffer, r, &frames_out) < 0)
                    ok = 0;
            
        
        if (ok)
            printf("Success\\n");
        else
            printf("Failure\\n");
        printf("Playback:\\n");
        showstat(phandle, frames_out);
        printf("Capture:\\n");
        showstat(chandle, frames_in);
        showinmax(in_max);
        if (p_tstamp.tv_sec == c_tstamp.tv_sec &&
            p_tstamp.tv_usec == c_tstamp.tv_usec)
            printf("Hardware sync\\n");
        snd_pcm_drop(chandle);
        snd_pcm_nonblock(phandle, 0);
        snd_pcm_drain(phandle);
        snd_pcm_nonblock(phandle, !block ? 1 : 0);
        if (ok) 
#if 1
            printf("Playback time = %li.%i, Record time = %li.%i, diff = %li\\n",
                   p_tstamp.tv_sec,
                   (int)p_tstamp.tv_usec,
                   c_tstamp.tv_sec,
                   (int)c_tstamp.tv_usec,
                   timediff(p_tstamp, c_tstamp));
#endif
            break;
        
        snd_pcm_unlink(chandle);
        snd_pcm_hw_free(phandle);
        snd_pcm_hw_free(chandle);
    
    snd_pcm_close(phandle);
    snd_pcm_close(chandle);
    return 0;

录音设备这里写得比较复杂可以参考我上传的书籍资料里面的课件。

参考资料:

《Linux高级程序设计第三版(中文)》        作者:杨宗德

《Linux环境编程图文指南》        作者:林世霖

ALSA官网:ALSA project - the C library reference: Index, Preamble and License

百问网:深圳百问网科技有限公司

alsa-lib以及pdf书籍资料链接:CSDN

python学习笔记11 ----网络编程

网络编程

网络编程需要知道的概念 

1.网络体系结构就是使用这些用不同媒介连接起来的不同设备和网络系统在不同的应用环境下实现互操作性,并满足各种业务需求的一种粘合剂。网络体系结构解决互质性问题彩是分层方法。

网络(OSI)的7层模型:

应用层--->为应用程序提供网络通信服务

表示层--->数据表示

会话层--->主机间通信(两个应用进程间)

传输层--->端到端的连接,隔离网络的上下层协议,使得网络应用与下层协议无关

网络层--->寻找最优路径,转发数据包

数据链路层--->无差错的链路连接

物理层--->二进制传输

技术分享技术分享

2.端口

  是一种抽象的软件结构,包括一些数据结构和I/O缓冲区。与协议有关。

3.套接字存在于通信区域中。通信区域也叫地址族,它是一个抽象的概念,主要用于将通过套接字通信的进程的共有特性综合在一起。

为保证数据的正确性,在网络协议中需要制定网络字节顺序,采用统一的网络字节顺序。

网络通信三要素:

  IP地址:用于表示主机(IP地址 = 网络ID+主机ID)

  端口号:用于标识进程的逻辑端口

  传输协议:TCP UDP

网络通信过程就是一个不断封装和解析的过程

Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定操作与驱动程序建立关系。

套接字

  套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。

套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳。许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持。

三种最流行的套接字类型是:stream,datagram和raw。stream和datagram套接字可以直接与TCP协议进行接口,而raw套接字则接口到IP协议。但套接字并不限于TCP/IP。

套接字模块 -------SOCKET()模块

  套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序。 

   

soc                           

SOCKET内建方法

函数  描述
服务器端套接字函数  
s.bind()   绑定地址(主机,端口号对)到套接字
s.listen() 开始TCP 监听
s.accept()   被动接受TCP 客户的连接,(阻塞式)等待连接的到来
客户端套接字函数  
s.connect() 主动初始化TCP 服务器连接
s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛异常
公共用途的套接字函数  
s.recv() 接收TCP 数据
s.send() 发送TCP 数据
s.sendall() 完整发送TCP 数据
s.recvfrom() 接收UDP 数据
s.sendto() 发送UDP 数据
s.getpeername()     连接到当前套接字的远端的地址
s.getsockname() 当前套接字的地址
s.getsockopt()     返回指定套接字的参数
s.setsockopt()     设置指定套接字的参数
s.close() 关闭套接字
面向模块的套接字函数  
s.setblocking()  设置套接字的阻塞与非阻塞模式
s.settimeout()a 设置阻塞套接字操作的超时时间
s.gettimeout()a 得到阻塞套接字操作的超时时间
面向文件的套接字的函数  
s.fileno() 套接字的文件描述符
s.makefile()     创建一个与该套接字关连的文件
a. Python 2.3 版本新加入的函数  

建立服务器连接需要六个步骤:

  1.创建socket对象。调用socket构造函数。

  socket=socket.socket(familly,type)

  family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程间通讯),也可以是AF_INET(对于IPV4协议的TCP和 UDP),至于type参数,SOCK_STREAM(流套接字)或者 SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。

  2.则是将socket绑定(指派)到指定地址上,socket.bind(address)

  address必须是一个双元素元组,((host,port)),主机名或者ip地址+端口号。如果端口号正在被使用或者保留,或者主机名或ip地址错误,则引发socke.error异常。

  3.绑定后,必须准备好套接字,以便接受连接请求。

  socket.listen(backlog)

backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,则拒绝请求。

  4.服务器套接字通过socket的accept方法等待客户请求一个连接:

  connection,address=socket.accept()

调用accept方法时,socket会进入‘waiting‘(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回 一个含有俩个元素的元组,形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客 户通信;第二个元素(address)是客户的internet地址。

  5.  处理阶段,服务器和客户通过send和recv方法通信(传输数据)。服务器调用send,并采用字符串形式向客户发送信息。send方法 返回已发送的字符个数。服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受 数据时会进入‘blocket‘状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接 受端。以后调用recv时,多余的数据会从缓冲区删除。

  6. 传输结束,服务器调用socket的close方法以关闭连接。

建立一个简单客户连接则需要4个步骤。

第1步,创建一个socket以连接服务器 socket=socket.socket(family,type)

第2步,使用socket的connect方法连接服务器 socket.connect((host,port))

第3步,客户和服务器通过send和recv方法通信。

第4步,结束后,客户通过调用socket的close方法来关闭连接。

技术分享

技术分享
import socket
sk = socket.socket()
address = (127.0.0.1,8000)
sk.bind(address)     
sk.listen(2)
print("......")
while True:
    conn, addr = sk.accept()
    print(addr)
    while True:
        try:
            date = conn.recv(1024)
        except Exception:
            break
        if not date:break
        print(str(date, "utf8"))
        inp = input(">>>>:")
        conn.send(bytes(inp,"utf8"))
# conn, addr = sk.accept()
# while True:
#     date = conn.recv(1024)
#     if not date:
#         conn, addr = sk.accept()
#         continue
#     print(str(date, "utf8"))
#     inp = input(">>>>:")
#     conn.send(bytes(inp,"utf8"))
# conn.close()
conn.close()
服务端
技术分享
import socket
sk = socket.socket()
address = ("127.0.0.1",8000)
sk.connect(address)
while True:
    inp = input(">>>>:")
    if inp == "q":
        break
    sk.send(bytes(inp, "utf8"))
    date = sk.recv(1024)
    print(str(date,"utf8"))
sk.close()
客户端

简单的模拟qq对话(socket模块

技术分享
import socket,subprocess
sk = socket.socket()
address = (0.0.0.0,8000)
sk.bind(address)
sk.listen(2)
print("......")
while True:
    conn, addr = sk.accept()
    print(addr)
    while True:
        try:
            date = conn.recv(1024)
        except Exception:
            break
        if not date:break
        print(str(date, "utf8"))
        obj = subprocess.Popen(str(date, "utf8"),shell=True,stdout=subprocess.PIPE)
        cmd_result = obj.stdout.read()
        result_len = str(len(cmd_result))
        print(result_len)
        conn.send(bytes(result_len,"utf8"))
        conn.send(cmd_result)
    conn.close()
server
技术分享
import socket
sk = socket.socket()
address = ("127.0.0.1",8000)
sk.connect(address)
while True:
    inp = input(">>>>:")
    if inp == "q":
        break
    sk.send(bytes(inp, "utf8"))
    result_len = int(str(sk.recv(1024),"utf8"))
    print(result_len)
    date = bytes()
    while len(date) != result_len:
        da = sk.recv(1024)
        date+=da
    print(str(date,"gbk"))
sk.close()
client

简单的FTP上传图片

技术分享

技术分享
import subprocess
import socket
import os
sk=socket.socket()
print(sk)
address=(127.0.0.1,8000)
sk.bind(address)
sk.listen(3)
print(waiting......)
BASE_DIR=os.path.dirname(os.path.abspath(__file__))


while 1:
    conn, addr = sk.accept()
    while 1:
        data=conn.recv(1024)
        cmd,filename,filesize=str(data,utf8).split(|)
        path=os.path.join(BASE_DIR,tupian,filename)
        filesize=int(filesize)


        f=open(path,ab)

        has_receive=0
        while has_receive!=filesize:
            data=conn.recv(1024)
            f.write(data)
            has_receive+=len(data)

        f.close()
server
技术分享
import socket
import os
sk=socket.socket()
address=(127.0.0.1,8000)
sk.connect(address)

BASE_DIR=os.path.dirname(os.path.abspath(__file__))

while True:
    inp=input(>>>).strip()#   post|11.png

    cmd,path=inp.split(|)

    path=os.path.join(BASE_DIR,path)
    filename=os.path.basename(path)
    file_size=os.stat(path).st_size

    file_info=post|%s|%s%(filename,file_size)

    sk.sendall(bytes(file_info,utf8))

    f=open(path,rb)

    has_sent=0
    while has_sent!=file_size:
         data=f.read(1024)
         sk.sendall(data)
         has_sent+=len(data)

    f.close()
    print(上传成功)
client

 

以上是关于linuxALSA应用编程笔记的主要内容,如果未能解决你的问题,请参考以下文章

Linux audio驱动模型

一篇很棒的C语言入门笔记!

Linux C编程之一:Linux下c语言的开发环境

Linux学习笔记-Shell教程

Linux学习笔记之shell编程基础

Linux C编程一站式学习笔记5