从标准输入读取字节时发生延迟(使用管道)
我正在编写一个 C 程序,它将 sox
的输出作为我的程序的输入。一般来说,我的程序会从 stdin 读取输入,然后进行一些处理。但是,当我从 stdin
读取字节值并将其写回另一个文件(只是为了确保一切正确)时,我发现我的结果以某种方式被延迟(我对此不太确定),与原始波形相比(图像是这里,波形上面是输出sox
的命令)。
有人可以帮我指出我哪里出错了吗?我已经为这个问题苦苦挣扎了好几个小时。我使用的是 Ubuntu 20.04。谢谢! (如果您想要我的音频文件,这里就是)
< strong>Sox命令生成上面的波形
cat arctic_a0010.wav | sox -t wav - -b 16 -e signed -t raw - > mid.raw
命令生成下面的波形
cat arctic_a0010.wav | sox -t wav - -b 16 -e signed -t raw - | ./test
我的最小test.c
节目
#include <stdio.h>
#include <stdlib.h>
void storeValue(short* arr, short* assignValue, long int startPt, long int numBlock) {
for (long int i = 0; i < numBlock; i++) {
arr[startPt + i] = assignValue[i];
}
}
void readFromStdin(short* arr, long* curSize) {
long r, n = 0;
int BUFFER_SIZE = 1024;
short buffer[BUFFER_SIZE];
freopen(NULL, "rb", stdin);
while (1) {
r = fread(buffer, sizeof(short), BUFFER_SIZE, stdin);
if (r <= 0) {
break;
}
if (n + r > *curSize) {
*curSize = n + r;
arr = (short*)realloc(arr, (*curSize) * sizeof(short));
}
storeValue(arr, buffer, n, r);
n = n + r;
}
}
int main(int argc, char *argv[])
{
// Read from stdin
short* inputArray = (short*)malloc(sizeof(short));
long InpSize = 1, currentIndex = 0;
readFromStdin(inputArray, &InpSize);
// Write to file
FILE *out = fopen("test.raw", "wb");
fwrite(inputArray, sizeof(short), InpSize, out);
}
I am writing a C program that take sox
's output as input for my program. Generally, my program would read the input from stdin
and make some processing afterward. However, when I read byte values from stdin
and wrote it back to another file (just to make sure everything is correct), I saw that my result was somehow be delayed (I am not sure about this), comparing to the original one (image is here, the waveform above is the output of sox
's command).
Can someone point out for me where do I go wrong please? I have been struggled with this issue for so many hours. I am using Ubuntu 20.04. Thanks! (In case you want my audio file, here it is)
Sox command to generate above waveform
cat arctic_a0010.wav | sox -t wav - -b 16 -e signed -t raw - > mid.raw
Command to generate below waveform
cat arctic_a0010.wav | sox -t wav - -b 16 -e signed -t raw - | ./test
My minimal test.c
program
#include <stdio.h>
#include <stdlib.h>
void storeValue(short* arr, short* assignValue, long int startPt, long int numBlock) {
for (long int i = 0; i < numBlock; i++) {
arr[startPt + i] = assignValue[i];
}
}
void readFromStdin(short* arr, long* curSize) {
long r, n = 0;
int BUFFER_SIZE = 1024;
short buffer[BUFFER_SIZE];
freopen(NULL, "rb", stdin);
while (1) {
r = fread(buffer, sizeof(short), BUFFER_SIZE, stdin);
if (r <= 0) {
break;
}
if (n + r > *curSize) {
*curSize = n + r;
arr = (short*)realloc(arr, (*curSize) * sizeof(short));
}
storeValue(arr, buffer, n, r);
n = n + r;
}
}
int main(int argc, char *argv[])
{
// Read from stdin
short* inputArray = (short*)malloc(sizeof(short));
long InpSize = 1, currentIndex = 0;
readFromStdin(inputArray, &InpSize);
// Write to file
FILE *out = fopen("test.raw", "wb");
fwrite(inputArray, sizeof(short), InpSize, out);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C 按值传递参数。这包括指针参数。与所有按值参数一样,更改函数作用域内的值对于调用者来说没有任何意义。如果您想向调用者传达值的变化,有多种方法可以实现,最常见的方法如下所示:
使用否则无价值的返回值
现在您的函数返回
void< /code> (例如什么都没有)。更改它以将更改的(可能已更新的)结果发送到
arr
。像这样:在
main
中:形式指针参数传递地址
如果你想改变一个实际参数,你需要记住C是pass-by-价值。因此,您需要操纵参数以接受要更改的“事物”的地址,并将该地址作为调用站点的正式参数传递。即使是最新手的 C 程序员也熟悉简单的整数交换:
请注意,这会更改
main
中的a
和b
中存储的值,因为它们的地址用作指针类型形式参数的参数,并且取消引用允许我们随后将数据驱动到它们中。现在,考虑一下:
arr =
没有进行取消引用,这与从
main
调用foo
如果你想通过通过“引用”进行某些操作,方法是将形参声明为类型指针(其中“type”是基础数据类型),并传递 var 的地址,就像我们上面所做的那样
swap_int
。即使参数已经是指针类型,也是如此。在这些情况下,形式参数变成了指针到类型的指针,调用点的参数是指针变量的地址
换句话说,最终:
过多的其他东西(不是检查你的 realloc 结果、转换 malloc 等)都是额外修复的燃料,但主要问题可以通过上述技术中的任何一种来解决。
C passes arguments by value. That includes pointer arguments. Like all by-value arguments, changing the value within a function scope means nothing to the caller. If you want to convey a change in value to the caller there are multiple ways to do it, the most common shown below:
Use That Otherwise-Worthless Return Value
Right now your function returns
void
(e.g. nothing). Change it to send the (possibly updated) result of changes toarr
. Like this:and in
main
:Formal Pointer-To Argument an Pass By Address
If you want to change an actual argument, you need to remember that C is pass-by-value. Therefore, you need to rig the parameter to accept an address of the 'thing' you want to change, and pass that address as the formal argument at the call site. Even the most novice C programmer is familiar with a simple integer swap:
Note this changes the values stored in
a
andb
inmain
because their addresses are used as arguments to pointer-type formal parameters, and dereferencing allows us to drive data into them thereafter.Now, consider this:
There is no dereferencing going on with
arr =
It is no different than thisCalling
foo
frommain
If you want to pass something by "reference", the way to do it is to declare the formal parameter to be pointer-to-type (where 'type' is the underlying data type), and pass the address of your var, just like we did above in
swap_int
.This is true, even when the parameters are already pointer types. In those cases, the formal parameters become pointer-to-pointer-to-type, and the arguments from the call site are the addresses of pointer variables
In other words, at long last:
The plethora of other things (not checking your realloc results, casting mallocs, etc.) are all fuel for additional fixes, but the main problem can be addressed in either of the above techniques.