【问题标题】:sound wave sawtooth in cc中的声波锯齿
【发布时间】:2019-04-29 14:48:58
【问题描述】:

我正在尝试在 c 中生成锯齿波。 我的工作快结束了,但我有问题必须解决。 我在下面附上了clode。

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <tgmath.h>

/******************************
*  Magic file format strings. *
******************************/
const char fChunkID[]     = {'R', 'I', 'F', 'F'};
const char fFormat[]      = {'W', 'A', 'V', 'E'};
const char fSubchunk1ID[] = {'f', 'm', 't', ' '};
const char fSubchunk2ID[] = {'d', 'a', 't', 'a'};

/********************************
* WriteWavePCM() configuration: *
* - 2 channels,                 *
* - frequency 44100 Hz.         *
********************************/
const unsigned short N_CHANNELS = 2;
const unsigned int SAMPLE_RATE = 48000;
const unsigned short BITS_PER_BYTE = 8;

bool WriteWavePCM(short* sound, size_t pairAmount, char* fileName){
    const static unsigned int fSubchunk1Size = 16;
    const static unsigned short fAudioFormat = 1;
    const static unsigned short fBitsPerSample = 16;

    unsigned int fByteRate = SAMPLE_RATE * N_CHANNELS * fBitsPerSample / BITS_PER_BYTE;

    unsigned short fBlockAlign = N_CHANNELS * fBitsPerSample / BITS_PER_BYTE;
    unsigned int fSubchunk2Size;
    unsigned int fChunkSize;

    FILE* fout;
    size_t ws;

    if (!sound || !fileName || !(fout = fopen( fileName, "w" ))) return false;

    fSubchunk2Size = pairAmount * N_CHANNELS * fBitsPerSample / BITS_PER_BYTE;
    fChunkSize = 36 + fSubchunk2Size;

    // Writing the RIFF header:
    fwrite(&fChunkID, 1, sizeof(fChunkID),      fout);
    fwrite(&fChunkSize,  sizeof(fChunkSize), 1, fout);
    fwrite(&fFormat, 1,  sizeof(fFormat),       fout);

    // "fmt" chunk:
    fwrite(&fSubchunk1ID, 1, sizeof(fSubchunk1ID),      fout);
    fwrite(&fSubchunk1Size,  sizeof(fSubchunk1Size), 1, fout);
    fwrite(&fAudioFormat,    sizeof(fAudioFormat),   1, fout);
    fwrite(&N_CHANNELS,      sizeof(N_CHANNELS),     1, fout);
    fwrite(&SAMPLE_RATE,     sizeof(SAMPLE_RATE),    1, fout);
    fwrite(&fByteRate,       sizeof(fByteRate),      1, fout);
    fwrite(&fBlockAlign,     sizeof(fBlockAlign),    1, fout);
    fwrite(&fBitsPerSample,  sizeof(fBitsPerSample), 1, fout);

    /* "data" chunk: */
    fwrite(&fSubchunk2ID, 1, sizeof(fSubchunk2ID),      fout);
    fwrite(&fSubchunk2Size,  sizeof(fSubchunk2Size), 1, fout);

    /* sound data: */
    ws = fwrite(sound, sizeof(short), pairAmount * N_CHANNELS, fout);
    fclose(fout);
    return true;
}

////////////////////////////////////////////////

const unsigned int N_SAMPLE_PAIRS = 50000;

int main(int argc, char* argv[]){
    short* sound;
    int i;
    int j;
    bool status;
    char* file_name;
    int l; // dodane

    sound = (int*) malloc(sizeof(int) * N_SAMPLE_PAIRS * N_CHANNELS );

    if (!sound)
    {
        puts("Could not allocate space for the sound data.");
        return (EXIT_FAILURE);
    }

    int amplitude = 10000;
    int frequency = 80;
    short record = 0;
    short waveNumber = 1;
    int samplesPerWavelength = SAMPLE_RATE / (frequency/N_CHANNELS);
    int soundLen = 10 * samplesPerWavelength;
    int ampStep = (int)((amplitude*2)/(int)samplesPerWavelength);
    short step = 5*samplesPerWavelength;
    short muteRate = amplitude/(soundLen/samplesPerWavelength);
    int totalSamplesWritten = 0;
    int tempSample =0;

    for (i=0, j=0; i<N_SAMPLE_PAIRS*N_CHANNELS; i+=2, j++) {
        ampStep = (int)((amplitude*2)/(int)samplesPerWavelength);
        tempSample = (int)((totalSamplesWritten%samplesPerWavelength)*ampStep);
        sound[i] = tempSample;
        sound[i+1] = tempSample;
        totalSamplesWritten++;
    }


    file_name = argc > 1 ? argv[1] : "Default2.wav";
    status = WriteWavePCM(sound, N_SAMPLE_PAIRS, file_name);


    free(sound);

    if (status)
    {
        printf("Discotheque is ready in \"%s\"\n", file_name);
    }
    else
    {
        puts( "Something seems to have gone wrong." );
        return (EXIT_FAILURE);
    }

    return 0;
}

这是我的结果。有锯齿,但行为奇怪。我不知道为什么会有这个。我检查了我的样本数组,一切看起来都不错。

有人可以帮助我吗?我被困住了,我不知道该怎么办。我在 2 个不同的程序中检查了它:audiocity 和 wavepadaudio,在这两个程序中,这种行为都存在。所以我肯定对我的代码有问题。请帮帮我。

【问题讨论】:

  • 似乎对我有用...您如何编译/运行它?你能看出有多少样本看起来已经损坏了吗?
  • 我注意到你有 int soundLen = 10 * samplesPerWavelength; 和 3 行之后是 soundLen / samplesPerWavelength,我们可以看到是 10。整数运算似乎在这里完全可以工作,但还有其他相同的例子吗?
  • 我正在使用代码块来编译它。如果您在循环中 printf tempSample,您可以看到它们没有损坏。你能告诉我你编译后的样子吗?
  • MSVC 编译显示相同的故障,但请注意两个编译器警告:(a) '=': 不兼容的类型 - 从 'int *' 到 'short *' 和 (b) '
  • 您似乎在某种程度上依赖于整数类型的特定表示形式——包括大小和字节顺序。我不确定您的假设在使用您的特定编译器编译时是否与 WAV 格式匹配。健壮的代码会更加小心这样的事情。

标签: c audio wav


【解决方案1】:

这是我得到的输出的一些屏幕截图。对我来说似乎很好。

使用内置规范。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/5.4.0/lto-wrapper.exe 目标:i686-pc-cygwin 配置:/cygdrive/i/szsz/tmpp/gcc/gcc-5.4.0-1.i686/src/gcc-5.4.0/configure --srcdir=/cygdrive/i/szsz/tmpp/gcc/gcc- 5.4.0-1.i686/src/ gcc-5.4.0 --prefix=/usr --exec-prefix=/usr --localstatedir=/var --sysconfdir=/etc --docdir=/usr/share/doc/gcc --htmldir=/usr/分享/doc/gcc/h tml -C --build=i686-pc-cygwin --host=i686-pc-cygwin --target=i686-pc-cygwin --without-libiconv-prefix --without-libintl-prefix --libexecdir= /usr/lib --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --enable-bootstrap --enable-__cxa_ate xit --with-dwarf2 --with-arch=i686 --with-tune=generic --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,java,lto,objc,obj-c++ --enable-graphite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enab le-libquadmath-support --enable-libssp --enable-libada --enable-libjava --enable-libgcj-sublibs --disable-java-awt --disable-symvers --with- ecj-jar=/usr/share/java/ecj.jar --with-gnu-ld --with-gnu-as --with-cloog-include=/usr/include/cloog-isl --without-libiconv-前缀--无- libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible 线程模型:posix gcc 版本 5.4.0 (GCC)

uname -a CYGWIN_NT-6.1-WOW DE-E03895 2.8.0(0.309/5/3) 2017-04-01 20:42 i686 Cygwin

这是您输出中损坏样本的屏幕截图;

【讨论】:

  • 所以你的答案是“为我工作”?很公平,但我相信 OP 会很高兴了解它可能对他们造成破坏的地方。
  • @JohnBollinger 他问“你能告诉我编译后它的样子吗?”我知道如何发布图片的唯一方法是在答案中。
  • 谢谢,现在我知道我的编译器或输出文件有问题。更接近解决问题
  • 故障的爆发很好。尤其令人怀疑的是,虽然每个通道中的毛刺具有相同的大致形状,但它们并不完全相同。幅度和相位都有些不同。
【解决方案2】:

当我查看文件转储(MSVC 编译)时,我注意到一些 0D 0A 数据对。然后我改变了这个

fout = fopen( fileName, "w" )

为此指定一个二进制文件

fout = fopen( fileName, "wb" )

现在故障已经消失了。

注意

如果mode中没有给出tb,则默认翻译模式为 由全局变量_fmode定义。

所以默认翻译模式一定是“文本”。

【讨论】:

  • 这就解释了一切。不错的收获。
猜你喜欢
  • 2018-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-10
相关资源
最近更新 更多