1. 语音类实现 (实现读取wav/pcm,STFT)

news2024/10/6 8:39:10

[C++ 基于Eigen库实现CRN前向推理]

第一部分:WavFile.class (实现读取wav/pcm,实现STFT)

  • 前言:(Eigen库使用记录)
  • 第一部分:WavFile.class (实现读取wav/pcm,实现STFT)
  • 第二部分:Conv2d实现
  • 第三部分:TransposedConv2d实现 (mimo,padding,stride,dilation,kernel,outpadding)
  • 第四部分:NonLinearity (Sigmoid,Tanh,ReLU,ELU,Softplus)
  • 第五部分:LSTM
  • GITHUB仓库

1. 读写语音文件(wav/pcm)

1.1 wav文件读写

语音文件有很多后缀格式,这里只实现了两种后缀名,.wav和.pcm。

  • WAV文件遵守资源交换文件格式之规则,在文件的前44(或46)字节放置标头(header),使播放器或编辑器能够简单掌握文件的基本信息,其内容以区块(chunk)为最小单位,每一区块长度为4字节,而区块之上则由子区块包裹,每一子区块长度不拘,但须在前头先宣告标签及长度(字节)。
  • 标头的前3个区块记录文件格式及长度;
  • 接着第一个子区块包含8个区块,记录声道数量、采样率等信息;
  • 接着第二个子区块才是真正的音频资料,长度则视音频长度而定。
  • 内容如下表所示。须注意的是,每个区块的端序不尽相同,而音频内容本身则是采用小端序。

在这里插入图片描述

  • 读Wav文件
    图中所示是一个wav的标准格式,但wav还有其他不同的存储格式,有些有扩展块之类的,需要根据具体的语音文件来确定。比如我用python中soudfile生成的语音,其format_tag=3,format_length=18(通常为16)。由于我没用到其他格式的情况,直接在下方用if else讨论format_tag=1和=3的情况。
    总而言之,读取wav其实就是一个解析头文件的过程,把对应的头信息存下来,再去读取数据就好了。-
    读wav文件的具体代码给出(后面会给整体的h文件和cpp文件):

    void Wav_File::LoadWavFile(const char *file_path) {
        FILE *fp = fopen(file_path, "rb");
        if (fp) {
            fread(this->id_riff, sizeof(char), 4, fp);
            this->id_riff[4] = '\0';
            fread(&this->file_size, sizeof(int16_t), 2, fp);
            fread(this->id_wave, sizeof(char), 4, fp);
            this->id_wave[4] = '\0';
            fread(this->id_fmt, sizeof(char), 4, fp);
            this->id_fmt[4] = '\0';
            fread(&this->format_length, sizeof(int16_t), 2, fp);
            fread(&this->format_tag, sizeof(int16_t), 1, fp);
            fread(&this->channels, sizeof(int16_t), 1, fp);
            fread(&this->sample_rate, sizeof(int16_t), 2, fp);
            fread(&this->avg_bytes_sec, sizeof(int16_t), 2, fp);
            fread(&this->block_align, sizeof(int16_t), 1, fp);
            fread(&this->bits_per_sample, sizeof(int16_t), 1, fp);
            if (this->format_tag == 1) {
                fread(this->id_data, sizeof(char), 4, fp);
                this->id_data[4] = '\0';
                fread(&this->data_size, sizeof(int16_t), 2, fp);
                this->wav_size = this->data_size / sizeof(int16_t);
                this->ip_raw = (int16_t *) malloc(this->data_size);
                fread(this->ip_raw, sizeof(int16_t), this->wav_size, fp);
    
                this->data = (float_t *) malloc(this->wav_size * sizeof(float_t));
                for (int i = 0; i < this->wav_size; i++) {
                    this->data[i] = (float_t) (this->ip_raw[i] * 1.0 / 32768);
                }
    
            } else if (this->format_tag == 3) {
                fread(&this->cb_size, sizeof(int16_t), 1, fp);
                fread(this->id_data, sizeof(char), 4, fp);
                this->id_data[4] = '\0';
                fread(&this->data_size, sizeof(int16_t), 2, fp);
                this->wav_size = this->data_size / sizeof(float);
                this->fp_raw = (float *) malloc(this->data_size);
                fread(this->fp_raw, sizeof(float), this->wav_size, fp);
                this->data = (float_t *) malloc(this->wav_size * sizeof(float_t));
                for (int i = 0; i < this->wav_size; i++) {
                    this->data[i] = this->fp_raw[i];
                }
            }
        }
        fclose(fp);
    
    }
    
  • 写出Wav文件
    Wav文件写出和读入是完全对应的,把读到的信息反向写出就可以了。
    如果对数据有所操作,需要去找对应的变量进行修改,比如长度,需要更新总文件的file_size以及data chunk的data_size。
    具体代码给出:

    void Wav_File::WriteWavFile(const char *dest_path) {
        for (int i = 0; i < wav_size; i++) {
            if (format_tag == 1)
                this->ip_raw[i] = (int16_t) (this->data[i] * 32768);
            else
                this->fp_raw[i] = this->data[i];
        }
    
        FILE *fp = fopen(dest_path, "wb");
        if (fp) {
    
            fwrite(this->id_riff, sizeof(char), 4, fp);
            fwrite(&this->file_size, sizeof(int16_t), 2, fp);
            fwrite(this->id_wave, sizeof(char), 4, fp);
            fwrite(this->id_fmt, sizeof(char), 4, fp);
            fwrite(&this->format_length, sizeof(int16_t), 2, fp);
            fwrite(&this->format_tag, sizeof(int16_t), 1, fp);
            fwrite(&this->channels, sizeof(int16_t), 1, fp);
            fwrite(&this->sample_rate, sizeof(int16_t), 2, fp);
            fwrite(&this->avg_bytes_sec, sizeof(int16_t), 2, fp);
            fwrite(&this->block_align, sizeof(int16_t), 1, fp);
            fwrite(&this->bits_per_sample, sizeof(int16_t), 1, fp);
            if (this->format_tag == 3) {
                fwrite(&this->cb_size, sizeof(int16_t), 1, fp);
            }
            fwrite(this->id_data, sizeof(char), 4, fp);
            fwrite(&this->data_size, sizeof(int16_t), 2, fp);
            if (this->format_tag == 1) {
                fwrite(this->ip_raw, sizeof(int16_t), this->wav_size, fp);
            } else if (this->format_tag == 3) {
                fwrite(this->fp_raw, sizeof(float), this->wav_size, fp);
            }
    
        }
        fclose(fp);
    
    }
    
    
1.2 PCM文件读写

PCM文件没有格式,是直接存的数据,所以需要自己知道采样率,通道数,以及数据类型,然后直接读写就可以了,代码如下:

void Wav_File::LoadPcmFile(const char *file_path) {
    FILE *fp = fopen(file_path, "rb");

    // 计算文件长度
    fseek(fp, 0L, SEEK_END);
    this->wav_size = ftell(fp) / sizeof(float);
    fseek(fp, 0L, SEEK_SET);

    //申请内存空间 这边自己知道存储的是float32,所以申请float的内存空间
    this->fp_raw = (float *) malloc(this->wav_size * sizeof(float));
    fread(this->fp_raw, sizeof(float), this->wav_size, fp);
    fclose(fp);

	// 这部分是统一转换成float32存在data里,因为wav是用int16存的
    for (int i = 0; i < this->wav_size; i++) {
        this->data[i] = this->fp_raw[i];
    }
}

void Wav_File::WritePcmFile(const char *dest_path) {
    for (int i = 0; i < this->wav_size; i++) {
        this->fp_raw[i] = this->data[i];
    }
    FILE *fp = fopen(dest_path, "wb");
    fwrite(this->fp_raw, sizeof(float), this->wav_size, fp);
    fclose(fp);
}

2. STFT实现

2.1 设置STFT参数,窗函数

这块主要设置窗长,窗移,窗函数类型等,并为频谱数据申请内存空间
提供了三种窗实现,hanning,hamming和sqrt窗(我自己叫的)。
可以看到有两份spec和mag,pha内存,spec是自定义复数类型,用于存储由蝶形算法生成的频谱(因为对FFT实现不是很熟悉,根据网上照猫画虎,只能对2^N窗长进行变换)。
而另一份是对应不同基的FFT,没搞懂是用的现成的,具体代码就不在这放了,可以去github上看。

void Wav_File::setSTFT(int64_t frame_size, int64_t frame_shift, const char *win_type) {
    this->frame_size = frame_size;
    this->frame_shift = frame_shift;
    this->fft_size = this->frame_size;
    this->frame_num = this->wav_size / frame_shift + 1;

    this->win_type = win_type;
    this->setWindow(this->win_type);

    this->spec = (Complex **) malloc((this->fft_size / 2 + 1) * sizeof(*spec));
    for (int i = 0; i < (this->fft_size / 2 + 1); i++)
        this->spec[i] = (Complex *) malloc(this->frame_num * sizeof(Complex));

    this->mag = (float_t **) malloc((this->fft_size / 2 + 1) * sizeof(*this->mag));
    for (int i = 0; i < (this->fft_size / 2 + 1); i++)
        this->mag[i] = (float_t *) malloc(frame_num * sizeof(float_t));

    this->phase = (float_t **) malloc((this->fft_size / 2 + 1) * sizeof(*this->phase));
    for (int i = 0; i < (this->fft_size / 2 + 1); i++)
        this->phase[i] = (float_t *) malloc(frame_num * sizeof(float_t));

    // nfft
    this->spec_real = (float_t **) malloc(this->frame_num * sizeof(*spec_real));
    for (int i = 0; i < this->frame_num; i++)
        this->spec_real[i] = (float_t *) malloc((this->fft_size / 2 + 1) * sizeof(float_t));

    this->spec_imag = (float_t **) malloc(this->frame_num * sizeof(*spec_imag));
    for (int i = 0; i < this->frame_num; i++)
        this->spec_imag[i] = (float_t *) malloc((this->fft_size / 2 + 1) * sizeof(float_t));

    this->spec_mag = (float_t **) malloc(this->frame_num * sizeof(*spec_mag));
    for (int i = 0; i < this->frame_num; i++)
        this->spec_mag[i] = (float_t *) malloc((this->fft_size / 2 + 1) * sizeof(float_t));

    this->spec_pha = (float_t **) malloc(this->frame_num * sizeof(*spec_pha));
    for (int i = 0; i < this->frame_num; i++)
        this->spec_pha[i] = (float_t *) malloc((this->fft_size / 2 + 1) * sizeof(float_t));


}

void Wav_File::setWindow(const char *winType) {
    double_t a0, a1;
    this->window = (float_t *) malloc(this->frame_size * sizeof(float_t));
    int frac = this->frame_size - 1;
    if (strcmp(winType, "hamming") == 0) {
        for (int i = 0; i < this->frame_size; i++) {
            this->window[i] = float(0.540000000 - 0.460000000 * cos(PI * 2 * i / frac));
        }
    } else if (strcmp(winType, "hanning") == 0) {
        for (int i = 0; i < this->frame_size; i++) {
            this->window[i] = float(0.500000000 - 0.500000000 * cos(PI * 2 * i / frac));
        }
    } else if (strcmp(winType, "sqrt") == 0) {
        for (int i = 0; i < this->frame_size; i++) {
            this->window[i] = (float) sqrtf((0.5f - 0.5f * cosf(i / (float) (this->frame_size - 1) * 2 * PI)));
        }
    }
}
2.2 2^N版FFT
void Wav_File::STFT() {
    std::vector<float_t> padding_data;
    for (int i = 0; i < this->frame_shift; i++)
        padding_data.push_back(this->data[this->frame_shift - i]);
    for (int i = 0; i < this->wav_size; i++)
        padding_data.push_back(this->data[i]);
    for (int i = 0; i < this->frame_shift; i++)
        padding_data.push_back(this->data[this->wav_size - i - 2]);

    this->real = (float_t *) malloc(sizeof(float_t) * this->frame_size);
    this->imag = (float_t *) malloc(sizeof(float_t) * this->frame_size);

    for (int i = 0; i < this->frame_num; i++) {
        for (int j = 0; j < this->frame_size; j++) {
            this->real[j] = padding_data[i * this->frame_shift + j] * this->window[j];
            this->imag[j] = 0.0;
        }

        FFT(this->real, this->imag, this->fft_size);

        for (int j = 0; j <= this->fft_size / 2; j++) {
            this->spec[j][i].real = this->real[j];
            this->spec[j][i].imag = this->imag[j];
        }
    }
}

void Wav_File::ISTFT() {
    this->real = (float_t *) malloc(sizeof(float_t) * this->frame_size);
    this->imag = (float_t *) malloc(sizeof(float_t) * this->frame_size);
    auto *temp = (float_t *) malloc(sizeof(float_t) * (data_size + 2 * frame_shift));
    auto *ola = (float_t *) malloc(sizeof(float_t) * (data_size + 2 * frame_shift));

    for (int i = 0; i < this->frame_num; i++) {
        //��N_FFT/2+1����N_FFT(����Գ�)
        for (int j = 0; j < this->fft_size / 2 + 1; j++) {
            real[j] = spec[j][i].real;
            imag[j] = spec[j][i].imag;
        }
        for (int j = this->fft_size / 2 + 1; j < this->fft_size; j++) {
            real[j] = spec[this->fft_size - j][i].real;
            imag[j] = -spec[this->fft_size - j][i].imag;
        }

        IFFT(real, imag, this->fft_size);

        for (int j = 0; j < frame_size; j++) {
            temp[i * frame_shift + j] += (real[j] * this->window[j]);
            ola[i * frame_shift + j] += (this->window[j] * this->window[j]);
        }
    }

    for (int i = 0; i < (frame_num + 1) * frame_shift; i++) {
        if (temp[i] != 0) {
            temp[i] /= ola[i];
        }
    }
    for (int i = 0; i < (frame_num - 1) * frame_shift; i++)
        this->data[i] = temp[i + frame_shift];

//    超出部分就保持原样,不降噪就好了
//    int sub = this->wav_size - (frame_num - 1) * frame_shift;
//    this->file_size -= sub;
//    this->wav_size -= sub;
//    this->data_size -= sub;
}

void Wav_File::FFT(float_t param_real[], float_t param_imag[], int16_t param_n) {
    float_t treal, timag, ureal, uimag, arg;
    int32_t m, k, j, t, index1, index2;
    auto *wreal = (float_t *) malloc(frame_shift * sizeof(float_t));
    auto *wimag = (float_t *) malloc(frame_shift * sizeof(float_t));


    this->bitrp(param_real, param_imag, param_n);

    arg = -2 * PI / param_n;
    treal = cosf(arg);
    timag = sinf(arg);
    wreal[0] = 1.0;
    wimag[0] = 0.0;
    for (j = 1; j < param_n / 2; j++) {
        wreal[j] = wreal[j - 1] * treal - wimag[j - 1] * timag;
        wimag[j] = wreal[j - 1] * timag + wimag[j - 1] * treal;
    }

    for (m = 2; m <= param_n; m *= 2) {
        for (k = 0; k < param_n; k += m) {
            for (j = 0; j < m / 2; j++) {
                index1 = k + j;
                index2 = index1 + m / 2;
                t = param_n * j / m;
                treal = wreal[t] * param_real[index2] - wimag[t] * param_imag[index2];
                timag = wreal[t] * param_imag[index2] + wimag[t] * param_real[index2];
                ureal = param_real[index1];
                uimag = param_imag[index1];
                param_real[index1] = ureal + treal;
                param_imag[index1] = uimag + timag;
                param_real[index2] = ureal - treal;
                param_imag[index2] = uimag - timag;
            }
        }
    }
    free(wreal);
    free(wimag);
}

void Wav_File::IFFT(float_t param_real[], float_t param_imag[], int16_t param_n) {
    float_t treal, timag, ureal, uimag, arg;
    int m, k, j, t, index1, index2;
    auto *wreal = (float_t *) malloc(frame_shift * sizeof(float_t));
    auto *wimag = (float_t *) malloc(frame_shift * sizeof(float_t));

    bitrp(param_real, imag, param_n);

    arg = 2 * PI / param_n;
    treal = cosf(arg);
    timag = sinf(arg);
    wreal[0] = 1.0;
    wimag[0] = 0.0;
    for (j = 1; j < param_n / 2; j++) {
        wreal[j] = wreal[j - 1] * treal - wimag[j - 1] * timag;
        wimag[j] = wreal[j - 1] * timag + wimag[j - 1] * treal;
    }

    for (m = 2; m <= param_n; m *= 2) {
        for (k = 0; k < param_n; k += m) {
            for (j = 0; j < m / 2; j++) {
                index1 = k + j;
                index2 = index1 + m / 2;
                t = param_n * j / m;
                treal = wreal[t] * param_real[index2] - wimag[t] * param_imag[index2];
                timag = wreal[t] * param_imag[index2] + wimag[t] * param_real[index2];
                ureal = param_real[index1];
                uimag = param_imag[index1];
                param_real[index1] = ureal + treal;
                param_imag[index1] = uimag + timag;
                param_real[index2] = ureal - treal;
                param_imag[index2] = uimag - timag;
            }
        }
    }

    for (j = 0; j < param_n; j++) {
        real[j] /= param_n;
        imag[j] /= param_n;
    }
    free(wreal);
    free(wimag);
}

void Wav_File::bitrp(float_t param_real[], float_t param_imag[], int16_t param_n) {
    int i, j, a, b, p;

    for (i = 1, p = 0; i < param_n; i *= 2) {
        p++;
    }
    for (i = 0; i < param_n; i++) {
        a = i;
        b = 0;
        for (j = 0; j < p; j++) {
            b = (b << 1) + (a & 1);    // b = b * 2 + a % 2;
            a >>= 1;        // a = a / 2;
        }
        if (b > i) {
            std::swap(param_real[i], param_real[b]);
            std::swap(param_imag[i], param_imag[b]);
        }
    }
}

2.3 nfft

不放了 看github吧

3. 其他相关操作

3.1 能量归一化
float_t Wav_File::getNorm(float_t scale) {
    if (scale == 0) {
        float_t square = 0.0;
        for (int i = 0; i < this->wav_size; i++) {
            square += powf(this->data[i], 2);
        }
        scale = sqrtf((float_t) this->wav_size / square);
        for (int i = 0; i < this->wav_size; i++) {
            this->data[i] *= scale;
        }
    } else {
        for (int i = 0; i < this->wav_size; i++) {
            this->data[i] /= scale;
        }
    }
    return scale;
}
3.2 求幅度谱
void Wav_File::getMagnitude() {
    for (int i = 0; i < this->frame_num; i++) {
        for (int j = 0; j < this->fft_size / 2 + 1; j++) {
            this->spec_mag[i][j] = sqrtf(powf(spec_real[i][j], 2) + powf(spec_imag[i][j], 2));
        }
    }
}
3.3 求相位谱
void Wav_File::getPhase() {
    for (int i = 0; i < this->frame_num; i++) {
        for (int j = 0; j < this->fft_size / 2 + 1; j++) {
            this->spec_pha[i][j] = atan2f(spec_imag[i][j], spec_real[i][j]);
        }
    }
}
3.4 幅度谱相位谱还原频谱
void Wav_File::magToSpec() {
    for (int i = 0; i < this->frame_num; i++) {
        for (int j = 0; j < this->fft_size / 2 + 1; j++) {
            spec_real[i][j] = this->spec_mag[i][j] * cosf(this->spec_pha[i][j]);
            spec_imag[i][j] = this->spec_mag[i][j] * sinf(this->spec_pha[i][j]);
        }
    }
}

4. 参考链接

[1] WAV文件格式详解
[2] GITHUB源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47227.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

荧光标记肽(Arg)9, FAM-labeled

(Arg)9, FAM-labeled 是一种带有 FAM 标记的 ARG&#xff0c;属于细胞穿透肽 (CPP)。CPPs 已成为一种强大的工具&#xff0c;用于将生物活性物质输送到完整细胞胞质中。(Arg)9, FAM-labeled, a cell-penetrating peptide (CPP), is a nona-arginine (ARG) with FAM label. CPPs…

mac上的python2安装

iiPython Release Python 2.7.18rc1 | Python.orgThe official home of the Python Programming Languagehttps://www.python.org/downloads/release/python-2718rc1/不小心把mac上的python2给删除了&#xff0c;发现老的nodejs项目需要pytho2&#xff0c;这下晕了&#xff0c;…

秸秆制粒机的总体设计

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1选题背景及意义 1 1.2国内外生物质制粒机的发展现状 4 1.2.1国外发展现状 4 1.2.2国内发展现状 5 1.3目前主要的制粒机类型及其制粒方法 9 1.3.1活塞式制粒机 9 1.3.2螺旋式制粒机 10 1.3.3模压颗粒制粒机 10 1.4秸秆燃料制粒加工技…

MES工单工艺线路条码系统NetMVC源码 MES条码管理系统源码

系统详情功能&#xff1a; 生产管理、基础数据维护、设备统计、新增设备统计、水质地图、故障统计、设备分布、耗材统计 生产管理&#xff1a;工单管理、工单检测、工单查询、工单生产、工位扫描、工位设置、滤芯包装、 包装打印、包装管理、条码管理、生产进度图 基础数据维…

性能测试之cpu 分析

cpu 架构 --中央处理器 运算器&#xff1a; 真正进行计算的单元控制器&#xff1a; leader寄存器&#xff1a; 存储 指令、数据、地址时钟 控制程序运行时长 内存 程序代码、网络数据&#xff0c;外部数据进入cpu的桥梁&#xff0c;内存的速度&#xff0c;要比cpu的速度 cp…

基于PHP+MySQL企业网络推广平台系统的设计与实现

企业网络推广平台系统具有很强的信息指导性特征,采用PHP开发企业网络推广平台系统 给web带来了全新的动态效果,具有更加灵活和方便的交互性。在Internet中实现数据检索越来越容易,可以及时、全面地收集、存储大量的企业资源信息以及进行发布、浏览、搜索相关的信息。让企业、个…

当世界杯撞上电商销售旺季,独立站卖家如何爆单不爆冷?

今年的世界杯频频爆冷&#xff0c;就像如今的天气一样&#xff0c;令人瑟瑟发抖。由于卡塔尔当地的特殊气候&#xff0c;2022年世界杯选择在冬季举行&#xff0c;于是就有了电商销售旺季遇上世界杯。两股热度叠加&#xff0c;造就了空前的销售时机。 感恩节、黑五、网一&#x…

CSDN【top1】Pytest接口测试框架实战项目搭建

一、前言 想想之前玩的框架&#xff0c;做的项目都是把数据用例冗余到一起的&#xff0c;不符合数据用例分离的思想&#xff0c;所以准备基于pytest搭建个测试框架&#xff0c;支持数据用例分离&#xff0c;接下来会用一系列文章逐步介绍整个框架是怎么搭建起来的。 二、项目结…

[附源码]计算机毕业设计springboot高校体育场馆管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

TMA三均线股票期货高频交易策略的R语言实现

趋势交易策略是至今应用最广泛以及最重要的投资策略之一&#xff0c;它的研究手段种类繁多&#xff0c;所运用的分析工具也纷繁复杂&#xff0c;其特长在于捕捉市场运动的大方向。股指期货市场瞬息万变&#xff0c;结合趋势分析方法&#xff0c;量化投资策略能够得到更有效的应…

项目使用smart-doc+Torna自动化创建api文档

首先部署Torna&#xff0c;我这里是用docker部署的 准备工作&#xff1a;1 docker 环境 2 torna 所需的sql脚本&#xff08;可以去github 找最新的&#xff09; DROP TABLE IF EXISTS compose_additional_page; CREATE TABLE IF NOT EXISTS compose_additional_page (id bigi…

jupyter使用教程及python语法基础

前言 上回说到搭建jupyter环境&#xff0c;今天的文章主要就是熟悉jupyter上的基本操作&#xff0c;以及python的一些基础语法。 正文 1、熟悉jupyter界面使用方法 通过命令行进入jupyter后&#xff0c;选择python3。 进去之后就是如下界面&#xff0c;要熟悉以下操作。当…

SAP ABAP——数据类型(二)【TYPES自定义数据类型详解】

&#x1f4ac;个人网站&#xff1a;【芒果个人日志】​​​​​​ &#x1f4ac;原文地址&#xff1a;SAP ABAP——数据类型&#xff08;二&#xff09;【TYPES自定义数据类型详解】 - 芒果个人日志 (wyz-math.cn) &#x1f482;作者简介&#xff1a; THUNDER王&#xff0c;一名…

python学习笔记(11)---(模块与包)

第九章 模块与包 1.模块&#xff08;modules&#xff09; &#xff08;1&#xff09;概念&#xff1a;将实现某一特定功能的代码放置在一个文件中&#xff0c;以便于其他程序进行导入使用&#xff0c;可以避免函数名、变量名的冲突&#xff0c;该文件称为模块&#xff0c;拓展…

RtspServer之LibRtsp解决闪退 新增鉴权(用户名密码登录)

编程语言&#xff1a;C 目标平台&#xff1a;arm&#xff08;hi3519&#xff09;注&#xff1a;因为代码是纯C语言按道理可以移植到各种平台 基础库&#xff1a;librtsp&#xff08;存在功能补全&#xff0c;有一定的bug&#xff09; 因为项目需求需要在海思平台实现IPC…

C++ Reference: Standard C++ Library reference: Containers: list: list: crend

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/crend/ 公有成员函数 <list> std::list::crend const_reverse_iterator crend() const noexcept; 返回反向结束的常量反向迭代器 返回一个const_reverse_iterator&#xff0c;指向容器中第一个元素…

领悟《信号与系统》之 采样定理

采样定理采样定理一、采样定理结论二、奈奎斯特间隔和频率计算公式及例题&#xff1a;三、信号自然采样&#xff08;脉冲采样&#xff09;四、信号理想采样&#xff08;冲激采样&#xff09;采样定理 连续时间信号也叫模拟信号。在一定条件之下&#xff0c;模拟信号可以用该信…

LDAP客户端操作方法

本文章简单介绍LDAP Admin客户端的使用方法&#xff0c;客户端工具地址为&#xff1a; https://download.csdn.net/download/u013896064/87209312 1、前提 我使用的是Ubuntu的虚拟机安装了一个LDAP服务&#xff0c;初始化完成并配置好密码&#xff0c;本次例子里面我使用的U…

nodejs+vue音乐网站与分享平台

目 录 摘 要 I 1 绪论 1 1.1研究背景 1 1.2研究现状 1 1.3研究内容 2 2 系统关键技术 3 2.1 Spring Boot框架 3 2.2 JAVA技术 3 2.3 MYSQL数据库 4 2.4 B/S结构 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2经济可行性…

Windows OpenGL 图像色彩替换

目录 一.OpenGL 图像色彩替换 1.原始图片2.效果演示 二.OpenGL 图像色彩替换源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 OpenGL…