为啥我的数组在 C 中返回错误的值?

Posted

技术标签:

【中文标题】为啥我的数组在 C 中返回错误的值?【英文标题】:Why is my array returning the wrong values in C?为什么我的数组在 C 中返回错误的值? 【发布时间】:2016-11-20 16:11:13 【问题描述】:

我正在尝试使用 libsndfile 库来读取/写入音频文件之间的信息。

我已经设法读取了原始文件,并用“水印”值写了一份副本。

我现在要做的就是打印值不为 0 的任何索引。

但是,当我调用 printBuffer() 函数时,即使在调试模式下,它也会返回全 0,我可以看到缓冲区中的值不为零/每次迭代都在更改。

我是否错误地调用了缓冲区数组?

我还是 C 的新手,所以如果您有任何建议,我们将不胜感激。

谢谢。

代码:

#define _CRT_SECURE_NO_DEPRECATE    
#include <stdio.h>
#include <stdlib.h>
#include <sndfile.h>
#include <time.h>

#define MAX_CHANNEL 2
#define BUF_SIZE 1024

int numItems(int frames, int channels);
void printInfo(int frames, int channels, int sampleRate);
void watermark(double *buffer, int count, int channels);
void watermark2(double *buffer, int count);
void readFile(int fileNumber);
void printBuffer(double *buffer, size_t count);

int main(void)


    int chosenFile, answer;

    printf("Please select the file you want to read\n");
    printf("1. File1\n");
    printf("2. File2\n");
    printf("3. File3\n");
    printf("4. File4\n");
    printf("5. File5\n");
    scanf("%d", &chosenFile);   

    processFile(chosenFile);
    /*
    Put boolean here to check whether to process the original file or the new one
    */
    printf("Would you like to read the new file?\n");
    printf("1. Yes\n");
    printf("2. No\n");
    scanf("%d", &answer);

    if (answer == 1)
    
        readFile(chosenFile);
    



int processFile(int fileNumber)

    /*READING FILE*/

    static double buffer[BUF_SIZE];
    SF_INFO info;
    SNDFILE *infile,*outfile;
    int readCount, i;


    /*
    Put boolean here to check whether it should read the original files, or the new output files

    */
    char *Files[] =  "File1.wav", "File2.wav", "File3.wav"
        , "File4.wav", "DFile5.wav" ;

    char *Files2[] =  "File1Output.wav", "File2Output.wav", "File3Output.wav"
        , "File4Output.wav", "File5Output.wav" ;

    char *inputFile = Files[fileNumber - 1];

    if (!(infile = sf_open(inputFile, SFM_READ, &info)))
    
        printf("Not able to open input file %s.\n", inputFile);
        puts(sf_strerror(NULL));
        return 1;
    ;


    printf("You have opened: %s\n", Files[fileNumber - 1]);
    printInfo( info.frames, info.channels, info.samplerate);
    int num = numItems(info.frames, info.channels);
    printf("Buffer(frames*channels): %d \n", num);


    /*WRITING FILE*/    
    char *outputFile = Files2[fileNumber - 1];
    printf("Your file has been saved in the following location: %s\n", outputFile);


    if (!(outfile = sf_open(outputFile, SFM_WRITE, &info)))
    
        printf("Not able to open output file %s.\n", outputFile);
        puts(sf_strerror(NULL));
        return 1;
    ;

    /*
    Actual buffer size is numItems, somehow can't declare buffer as buffer[numItems]
    BUF_SIZE is set to 1024, which means that it reads the data in chunks of 1024 frames
    it will keep writing in 1024 chuncks until all numItems have been written (numItems/BUF_SIZE)
    Needs to be on a while loop otherwise it will only write the first 1024 frames of the file
    */


    while ((readCount = sf_read_double(infile, buffer, BUF_SIZE)))
       

        watermark(buffer, readCount, info.channels);
        sf_write_double(outfile, buffer, readCount);
    ;


    for (i = 0; i < sizeof(buffer) / sizeof *buffer; i++)
    
        printBuffer(buffer, sizeof(buffer)/sizeof *buffer);
    


    /*
    Can only close SF_open once both reading/writing has been done
    if you close infile after the read, it's not able to copy the audio
    data from infile to write into outfile
    */
    sf_close(infile);
    sf_close(outfile);


    return;


void readFile(int fileNumber)

    SF_INFO info;
    SNDFILE *infile;

    char *Files[] =  "File1Output.wav", "File2Output.wav", "File3Output.wav"
        , "File4Output.wav", "File5Output.wav" ;

    char *inputFile = Files[fileNumber - 1];

    infile = sf_open(inputFile, SFM_READ, &info);

    printf("You have opened: %s\n", Files[fileNumber - 1]);
    printInfo(info.frames, info.channels, info.samplerate);

    sf_close(infile);

    return;




int numItems(int frames, int channels)

    int numItems = frames * channels;
    return numItems;

void printInfo(int frames, int channels, int sampleRate)

    printf("Number of Frames = %d\n", frames);
    printf("Number of Channels = %d\n", channels);
    printf("Sample Rate = %d\n", sampleRate);


void watermark(double *buffer, int count, int channels)
       
    double value[MAX_CHANNEL] =  0.0, 0.0 ;
    int i, j;

    if (channels > 1)
    
        /*
        Sets j to be the first channel and while i is less than 1024/5, i += channels
        buffer[3] value is multiplied by 0, and set to 0
        this mutes that particular index value or frame
        this keeps going until i>=1024/5 and then the next channel is chosen where j = 2
        buffer[4] value is multiplied by 0 and set to 0
        this keeps going until i>=1024/5 where it calls back to the while loop in processFile
        */

        for (j = 0; j < channels; j++)
        
            for (i = j; i < count / 5; i += channels)
            
                buffer[i] *= value[j];
            
        
    
    else
    
        /*
        If audio file has 1 channel, buffer[i] is set to 0 for all values < 1024/5 frames
        and it goes back to normal until the next 1024 frames where the first  1024/5 frames.
        */
        for (i = 0; i < count / 5; i++)
        
            buffer[i] *= value[0];
        
    

    return;


void printBuffer(double *buffer, size_t count)

    int i;

    for (i = 0; i < count; i++)
    
        if (i != 0)
            printf("%d\n", buffer[i]);
    


/*
- *DONE* - Need to create function that will read the newly outputted file 
- Find where the watermarks have been left on the audio
- Compare buffer[] values between original file and new outputted file
*/

【问题讨论】:

也许你的意思是写if(buffer[i]!=0)?您现在的条件只是跳过了第一次迭代。另外,你应该在printf()函数中使用%lf来打印双精度值。 @HonzaDejdar:您必须使用%lf 读取scanf() 等人中的双精度值。从 C99 开始,您可以(但不是要求)使用%lf 来格式化double 值。它是可选的原因是float 值通过适用于可变参数函数(例如printf)的默认提升规则自动提升为double,因此printf 永远不会传递float,因此%f用作 double 的原始传统格式(并且,由于默认升级规则,float 也是)。 @JonathanLeffler 感谢您的帖子,我不知道这一点。但是,OP 所有者使用了%d,我认为这是错误的:) @HonzaDejdar:是的,%d 无条件错误。常规使用%f打印double;使用%lf 是允许的,但不是必须的。我的狡辩(这只是一个狡辩,不是主要的抱怨,尽管它周围的所有措辞现在使它看起来很重要)已经结束'你应该使用%lf...'更准确地说'你应该使用%f(或者也许%lf,如果你关心的所有系统都有一个支持它的运行时,因为它只在C99中标准化)......'(而且它'你应该使用%f...' 会很简洁)。 @HonzaDejdar:是的!感谢您指出关于 if 语句以及双值格式的错误。 @JonathanLeffler:感谢您解释值格式之间的差异。真的很感激 :) 使用 for 循环调用printBuffer,它不会像@BodoThiesen 提到的那样打印任何内容。一旦我将它添加到 while 循环中,它就会打印所有不为零的值,但这需要做很多工作。谢谢。 【参考方案1】:
while ((readCount = sf_read_double(infile, buffer, BUF_SIZE)))
   

    watermark(buffer, readCount, info.channels);
    sf_write_double(outfile, buffer, readCount);
;

在这里,你一次又一次地使用缓冲区来读取一些数据,给它加水印,然后写出来。只有完成后,你才能从缓冲区中打印出最后剩余的数据:

for (i = 0; i < sizeof(buffer) / sizeof *buffer; i++)

    printBuffer(buffer, sizeof(buffer)/sizeof *buffer);

所以,与

#define MAX_CHANNEL 2
#define BUF_SIZE 1024

和一个 16 位 44100 立体声的波形文件,你只会看到最后 5.8 毫秒的声音数据,如果你有像音乐这样的正常音频或几乎没有噪音的高质量录制语音,这可能几乎是无声的。

另外:根据读取的最后一个块,您会看到文件的尾部,然后是尾部之前的某些部分,就像您看到最后 3.2 毫秒和之前的 2.6 毫秒一样,这在最后一次读取调用。

/edit:好吧,可能是我弄错了数字,数据类型是双精度等等,但概念上的错误是一样的。

/edit 2:查看 Jonathan Leffler 的评论,我发现还有更多错误... - 我建议打开所有编译器警告,并尝试理解(并修复)它们。

【讨论】:

谢谢你。我什至没有考虑音频文件末尾的静音。我在while loop 中添加了for loop,但这需要更多的调整,这样我就不必查看所有数据,而只需查看其中的一小部分。非常感谢。

以上是关于为啥我的数组在 C 中返回错误的值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 javascript 调用回发并且我没有错误?

为啥 sklearn MinMaxScaler() 返回超出范围的值而不是错误?

MS Access:为啥我的组合框显示错误的值?

为啥指针不能传递正确的值(C)?

pyopencl 在数组中返回错误的 float3 值

为啥我的 Axios 实例没有在捕获的错误中返回响应?