从 stdin 读取字节时发生延迟(使用管道)
Delay occurred when reading bytes from stdin (Using pipe)
我正在编写一个 C 程序,它将 sox
的输出作为我程序的输入。通常,我的程序会从 stdin
读取输入,然后进行一些处理。但是,当我从 stdin
读取字节值并将其写回另一个文件(只是为了确保一切正确)时,我看到我的结果是 不知何故被延迟 (这个我不太确定),对比一下原来的(图片是here,上面的波形是sox
的命令输出)。
谁能指出我哪里出错了?我已经为这个问题苦苦挣扎了好几个小时。我正在使用 Ubuntu 20.04。谢谢! (如果你想要我的音频文件,here 就是)
生成上述波形的 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);
}
C 按值传递参数。这包括指针参数。与所有 by-value 参数一样,在函数作用域内更改值对调用者来说意味着 无意义。如果您想将价值的变化传达给调用者,有多种方法可以做到,最常见的如下所示:
使用那个 Otherwise-Worthless Return 值
现在你的函数 returns void
(例如什么都没有)。更改它以将更改的(可能更新的)结果发送到 arr
。像这样:
short *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 = realloc(arr, (*curSize) * sizeof *arr);
}
storeValue(arr, buffer, n, r);
n = n + r;
}
return arr;
}
并在 main
中:
inputArray = readFromStdin(inputArray, &InpSize);
正式Pointer-To参数通过地址
如果你想改变实参,你需要记住C是pass-by-value。因此,您需要设置参数以接受要更改的 'thing' 的地址,并将该地址作为正式参数传递到调用站点。即使是最新手的 C 程序员也熟悉简单的整数交换:
#include <stdio.h>
void swap_int(int *pa, int *pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 1, b = 2;
swap_int(&a,&b);
printf("%d %d\n", a, b);
}
请注意,这会更改存储在 a
和 b
中 main
中的值,因为它们的地址用作 pointer-type 形式参数的参数,并且取消引用允许我们之后将数据写入其中。
现在,考虑一下:
void make_me_bigger(int *arr, int *size)
{
*size += 10;
arr = realloc(arr, *size * sizeof *arr);
}
arr =
没有取消引用,与此
没有什么不同
int foo(int x)
{
x = 20; // only changes x locally
}
从 main
调用 foo
int main()
{
int x = 10;
foo(x);
printf("%d\n", x); // still 10
}
如果你想通过“引用”传递一些东西,方法是将形参声明为pointer-to-type(其中'type'是底层数据类型),并通过你的 var 的地址,就像我们在上面 swap_int
.
中所做的一样
这是真的,即使参数已经是指针类型。在那些情况下,形式参数变为指向 pointer-to-type 的指针,而来自调用站点的参数是指针变量的地址
换句话说,终于:
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 = realloc(*arr, (*curSize) * sizeof **arr);
}
storeValue(*arr, buffer, n, r);
n = n + r;
}
}
过多的其他事情(不检查您的 realloc 结果、转换 malloc 等)都是额外修复的燃料,但主要问题可以通过上述任一技术解决。
我正在编写一个 C 程序,它将 sox
的输出作为我程序的输入。通常,我的程序会从 stdin
读取输入,然后进行一些处理。但是,当我从 stdin
读取字节值并将其写回另一个文件(只是为了确保一切正确)时,我看到我的结果是 不知何故被延迟 (这个我不太确定),对比一下原来的(图片是here,上面的波形是sox
的命令输出)。
谁能指出我哪里出错了?我已经为这个问题苦苦挣扎了好几个小时。我正在使用 Ubuntu 20.04。谢谢! (如果你想要我的音频文件,here 就是)
生成上述波形的 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);
}
C 按值传递参数。这包括指针参数。与所有 by-value 参数一样,在函数作用域内更改值对调用者来说意味着 无意义。如果您想将价值的变化传达给调用者,有多种方法可以做到,最常见的如下所示:
使用那个 Otherwise-Worthless Return 值
现在你的函数 returns void
(例如什么都没有)。更改它以将更改的(可能更新的)结果发送到 arr
。像这样:
short *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 = realloc(arr, (*curSize) * sizeof *arr);
}
storeValue(arr, buffer, n, r);
n = n + r;
}
return arr;
}
并在 main
中:
inputArray = readFromStdin(inputArray, &InpSize);
正式Pointer-To参数通过地址
如果你想改变实参,你需要记住C是pass-by-value。因此,您需要设置参数以接受要更改的 'thing' 的地址,并将该地址作为正式参数传递到调用站点。即使是最新手的 C 程序员也熟悉简单的整数交换:
#include <stdio.h>
void swap_int(int *pa, int *pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 1, b = 2;
swap_int(&a,&b);
printf("%d %d\n", a, b);
}
请注意,这会更改存储在 a
和 b
中 main
中的值,因为它们的地址用作 pointer-type 形式参数的参数,并且取消引用允许我们之后将数据写入其中。
现在,考虑一下:
void make_me_bigger(int *arr, int *size)
{
*size += 10;
arr = realloc(arr, *size * sizeof *arr);
}
arr =
没有取消引用,与此
int foo(int x)
{
x = 20; // only changes x locally
}
从 main
foo
int main()
{
int x = 10;
foo(x);
printf("%d\n", x); // still 10
}
如果你想通过“引用”传递一些东西,方法是将形参声明为pointer-to-type(其中'type'是底层数据类型),并通过你的 var 的地址,就像我们在上面 swap_int
.
这是真的,即使参数已经是指针类型。在那些情况下,形式参数变为指向 pointer-to-type 的指针,而来自调用站点的参数是指针变量的地址
换句话说,终于:
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 = realloc(*arr, (*curSize) * sizeof **arr);
}
storeValue(*arr, buffer, n, r);
n = n + r;
}
}
过多的其他事情(不检查您的 realloc 结果、转换 malloc 等)都是额外修复的燃料,但主要问题可以通过上述任一技术解决。