此代码不起作用 - 将数据从子例程传递到main并分配内存的问题。
子程序内的计算是正确的,但是main接收的值是不正确的 - main中的变量具有随机值,例如sRates。
#include <stdio.h>
#include <malloc.h>
#include "sndfile.h"
int main(int argc, char *argv[])
{
int sRates , sRatem , ret;
long nSamples=0, nSamplem;
float *datas, *datam;
printf("Read Test\n");
if (argc != 3) {
fprintf(stderr, "Expecting two wav file as argument\n");
return 1;
}
ret = readWav(argv[1], nSamples, sRates, &datas );
if (ret != 0) {
printf("Error\n");
}
// Output Info
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
nSamples, argv[1], sRates, (float)nSamples/sRates);
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
nSamples, argv[1], sRates, (float)nSamples/sRates);
// free(datas);
return 0;
}
int readWav(char *fname, long *numFrames, int *sRate, float **buffer )
{
// Open sound file
SF_INFO sndInfo;
SNDFILE *sndFile = sf_open(fname, SFM_READ, &sndInfo);
if (sndFile == NULL) {
fprintf(stderr, "Error reading source file '%s': %s\n", fname, sf_strerror(sndFile));
return 1;
}
printf("1Format of the audio file = %i\n", sndInfo.format);
printf("2Number of channels = %i\n", sndInfo.channels);
printf("3Sample Rate = %d\n", sndInfo.samplerate);
printf("4 Sample count = %ld\n", (long)sndInfo.frames);
sRate= sndInfo.samplerate;
// Allocate memory
buffer = (float *)malloc(sndInfo.frames * sndInfo.channels * sizeof(float));
if (buffer == NULL) {
fprintf(stderr, "Could not allocate memory for file\n");
sf_close(sndFile);
return 1;
}
// Load data
numFrames = sf_readf_float(sndFile, buffer, sndInfo.frames);
// Check correct number of samples loaded
if (numFrames != sndInfo.frames) {
fprintf(stderr, "Did not read enough frames for source\n");
sf_close(sndFile);
free(buffer);
// return 1;
}
else {
printf("Successfully read file\n");
numFrames = sndInfo.frames;
}
// Output Info
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
// numFrames, fname, sndInfo.samplerate, (float)numFrames/sndInfo.samplerate);
numFrames, fname, sRate, (float)numFrames/sndInfo.samplerate);
sf_close(sndFile);
// return(buffer);
return(0);
}
答案 0 :(得分:3)
在C中,所有参数都按值传递,因此如果你想要一个类似于参数的参数,你必须传递一个指针。由于您想要返回float*
,因此需要传递float**
。
实际上你传递的是,但你没有正确使用它(请使用-Wall
或等效的编译器来启用警告。)
代码应该或多或少地像这样:
int readWav(const char *fname, long *numFrames, int *sRate, float **buffer)
{
*buffer = malloc(...);
//if you do not feel comfortable writing `*buffer` everywhere:
float *data = *buffer;
///....
*numFrames = sf_readf_float(...);
///....
*sRate = sndInfo.samplerate;
///....
}
int main()
{
long nSamples;
int sRates;
float *datas;
ret = readWav(argv[1], &nSamples, &sRates, &datas);
//...
}
答案 1 :(得分:1)
您的代码中有几处错误
您没有声明readWav()
并且您从main()
调用它,它巧合,即因为它确实返回int
。< / p>
您正在将datas
的地址传递给readWav()
,请注意&datas
的类型为float **
,readWav()
期待{{1} }}
如果你打开了编译器警告,你就会注意到这一点。
您正在将float *
和nSamples
的值传递给sRate
,并且您希望主网中的readWav()
和nSamples
获得初始化后,您需要传递其地址。
您检查sRate
的返回值,但仍尝试访问readWav()
指针。
这是您的代码的固定版本
datas
提示:您应该尝试以只有一个退出点的方式编写您的函数,我喜欢使用#include <stdio.h>
#include "sndfile.h"
int readWav(const char *const fname, long *numFrames, int *sRate, float **buffer);
int main(int argc, char *argv[])
{
int sRates, sRatem, ret;
long nSamples = 0, nSamplem;
float *datas, *datam;
printf("Read Test\n");
if (argc != 3) {
fprintf(stderr, "Expecting two wav file as argument\n");
return 1;
}
ret = readWav(argv[1], &nSamples, &sRates, &datas);
if (ret != 0) {
printf("Error\n");
return 1;
}
// Output Info
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
nSamples, argv[1], sRates, (float)nSamples/sRates);
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
nSamples, argv[1], sRates, (float)nSamples/sRates);
free(datas);
return 0;
}
int readWav(const char *const fname, long *numFrames, int *sRate, float **buffer)
{
// Open sound file
SF_INFO sndInfo;
if ((sRate == NULL) || (numFrames == NULL) || (buffer == NULL)) {
fprintf(stderr, "Invalid arguments passed to readWav()\n");
return 1;
}
SNDFILE *sndFile = sf_open(fname, SFM_READ, &sndInfo);
if (sndFile == NULL) {
fprintf(stderr, "Error reading source file '%s': %s\n", fname, sf_strerror(sndFile));
return 1;
}
printf("1Format of the audio file = %i\n", sndInfo.format);
printf("2Number of channels = %i\n", sndInfo.channels);
printf("3Sample Rate = %d\n", sndInfo.samplerate);
printf("4 Sample count = %ld\n", (long)sndInfo.frames);
// Allocate memory
*buffer = malloc(sndInfo.frames * sndInfo.channels * sizeof(float));
if (*buffer == NULL) {
fprintf(stderr, "Could not allocate memory for file\n");
sf_close(sndFile);
return 1;
}
*sRate = sndInfo.samplerate;
// Load data
*numFrames = sf_readf_float(sndFile, *buffer, sndInfo.frames);
// Check correct number of samples loaded
if (*numFrames != sndInfo.frames) {
fprintf(stderr, "Did not read enough frames for source\n");
sf_close(sndFile);
free(*buffer);
}
else {
printf("Successfully read file\n");
*numFrames = sndInfo.frames;
}
// Output Info
printf("Read %ld frames from %s, Sample rate: %d, Length: %fs\n",
*numFrames, fname, *sRate, (float)*numFrames/sndInfo.samplerate);
sf_close(sndFile);
return(0);
}
,尽管宗教程序员相信goto
1}},它使您的代码更具可读性和可维护性。
我的意思是你可以有一个标签,你可以从函数中返回错误代码并进行所有清理,如下所示
goto