在2ch PCM上添加440HZ音调(合并PCM、噪声叠加)

在2ch PCM上添加440HZ音调(合并PCM、噪声叠加),c,merge,pcm,C,Merge,Pcm,我想在一个房间里加一些噪音 44100 Hz 2 channel 16 bit interleaved PCM 我正在生成1秒钟的440Hz噪声,并将其存储在噪声缓冲器中: #define SAMPLING_RATE 44100 int *noise_buffer; void generate_440(int *buffer) { int pos; // sample number we're on float volume = 0.1; // 0 to 1.0, one

我想在一个房间里加一些噪音

44100 Hz
2 channel
16 bit
interleaved PCM
我正在生成1秒钟的440Hz噪声,并将其存储在噪声缓冲器中:

#define SAMPLING_RATE 44100
int *noise_buffer;

void generate_440(int *buffer) {
    int pos;  // sample number we're on
    float volume = 0.1;  // 0 to 1.0, one being the loudest

    for (pos = 0; pos < SAMPLING_RATE; pos++) {
        float a = (2 * 3.14159) * pos / (SAMPLING_RATE / 440.0);
        float v = sin(a) * volume;

        // convert from [-1.0,1.0] to [-32768,32767]:
        buffer[pos] = remap_level_to_signed_16_bit(v);
    }
}
..
noise_buffer = (int *) malloc(SAMPLING_RATE * sizeof(int));
generate_440(noise_buffer);
但它会发出一种奇怪的声音。我认为问题与两个频道有关?遗憾的是,我还不熟悉音频数据


有人能帮我摆脱困境或把我推向正确的方向吗?

以下是我如何添加两个信号:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

#define SAMPLING_RATE 44100

int remap_level_to_signed_16_bit(float v)
{
  if (v >= 1)
    return 32767;

  if (v <= -1)
    return -32767;

  return v * 32767;
}

void generate_freq(int *buffer, size_t count, float volume, float freq)
{
  size_t pos; // sample number we're on

  for (pos = 0; pos < count; pos++) {
    float a = 2 * 3.14159f * freq * pos / SAMPLING_RATE;
    float v = sin(a) * volume;
    // convert from [-1.0,1.0] to [-32767,32767]:
    buffer[pos] = remap_level_to_signed_16_bit(v);
  }
}

void generate_noise(int *buffer, size_t count, float volume)
{
  size_t pos; // sample number we're on

  for (pos = 0; pos < count; pos++) {
    // random number [-1.0,1.0]
    float v = (rand() - RAND_MAX / 2.0f) * 2 / RAND_MAX * volume;
    // convert from [-1.0,1.0] to [-32767,32767]:
    buffer[pos] = remap_level_to_signed_16_bit(v);
  }
}

int add_two_16_bit_samples(int a, int b)
{
  int sum;

  // add a and b avoiding overflow
  if (a >= 0 && b >= 0) {
    if (a > INT_MAX - b) // mathematically equivalent to if (a + b > INT_MAX)
      sum = INT_MAX; // limit sum at INT_MAX if overflow
    else
      sum = a + b;
  } else if (a < 0 && b < 0) {
    if (a < INT_MIN - b) // mathematically equivalent to if (a + b < INT_MIN)
      sum = INT_MIN; // limit sum at INT_MIN if overflow
    else
      sum = a + b;
  } else {
    sum = a + b;
  }

  // limit sum to [-32767,32767]
  if (sum > 32767)
    sum = 32767;

  if (sum < -32767)
    sum = -32767;

  return sum;
}

void add_16_bit_samples(int *destination, const int* source, size_t count)
{
  for (; count--; destination++, source++) {
    *destination = add_two_16_bit_samples(*destination, *source);
  }
}

int save_16_bit_samples(const char* name, int* buf, size_t count, int stereo)
{
  FILE* f = fopen(name, "wb");
  int res = -1; // failure by default

  if (f != NULL) {

    while (count) {
      // convert sample to 2's complement unsigned representation
      unsigned v = *buf++;

      // separate it into 8-bit parts
      unsigned char c[2];
      c[0] = v & 0xFF; // LSB
      c[1] = (v >> 8) & 0xFF; // MSB

      // save it as little endian
      if (fwrite(c, 1, 2, f) != 2)
        break;

      // do once more if stereo
      if (stereo)
        if (fwrite(c, 1, 2, f) != 2)
          break;

      count--;
    }

    if (count == 0)
      res = 0; // success if all samples written out

    fclose(f);
  }

  return res;
}

int main(void)
{
  int* buf_440 = malloc(SAMPLING_RATE * sizeof(int));
  int* buf_noise = malloc(SAMPLING_RATE * sizeof(int));

  if (buf_440 == NULL || buf_noise == NULL) {
    printf("failed to allocate memory for samples\n");
    return EXIT_FAILURE;
  }

  generate_freq(buf_440, SAMPLING_RATE, 0.1f/*volume*/, 440.0f/*freq*/);
  generate_noise(buf_noise, SAMPLING_RATE, 0.01f/*volume*/);

  add_16_bit_samples(buf_440, buf_noise, SAMPLING_RATE);

  if (save_16_bit_samples("440noise.pcm", buf_440, SAMPLING_RATE, 1/*stereo*/)) {
    printf("failed to save samples to file\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
#定义采样率44100
整数重新映射级别到符号16位(浮点v)
{
如果(v>=1)
返回32767;
如果(v=0&&b>=0){
if(a>INT_MAX-b)//数学上等价于if(a+b>INT_MAX)
sum=INT_MAX;//如果溢出,则限制INT_MAX处的总和
其他的
总和=a+b;
}else if(a<0&&b<0){
if(a32767)
总和=32767;
如果(总和<-32767)
总和=-32767;
回报金额;
}
无效添加16位样本(整数*目的地、常数整数*源、大小\计数)
{
对于(;计数--;目标++,源++){
*目的地=添加两个16位样本(*目的地,*源);
}
}
int保存16位样本(常量字符*名称,int*buf,大小\u t计数,int立体声)
{
文件*f=fopen(名称,“wb”);
int res=-1;//默认情况下失败
如果(f!=NULL){
同时(计数){
//将样本转换为2的补码无符号表示
无符号v=*buf++;
//将其分成8位部分
无符号字符c[2];
c[0]=v&0xFF;//LSB
c[1]=(v>>8)&0xFF;//MSB
//另存为little endian
如果(fwrite(c,1,2,f)!=2)
打破
//如果是立体声,请再试一次
中频(立体声)
如果(fwrite(c,1,2,f)!=2)
打破
计数--;
}
如果(计数=0)
res=0;//如果已写出所有样本,则成功
fclose(f);
}
返回res;
}
内部主(空)
{
int*buf_440=malloc(采样率*sizeof(int));
int*buf_noise=malloc(采样率*sizeof(int));
if(buf_440==NULL | | buf_noise==NULL){
printf(“未能为样本分配内存\n”);
返回退出失败;
}
生成频率(buf_440,采样率,0.1f/*体积*/,440.0f/*频率*/);
产生噪声(buf噪声,采样率,0.01f/*体积*/);
添加16位采样(buf_440、buf_噪声、采样率);
如果(保存16位采样(“440noise.pcm”,buf\u 440,采样率,1/*立体声*/)){
printf(“未能将样本保存到文件\n”);
返回退出失败;
}
返回退出成功;
}

为什么不把样本加起来?不需要尝试对单个字节进行操作。你能帮我写一行C代码吗?我对C语言也很陌生,所以每一行对我来说都像是一本新书。提前谢谢!也许这个脚本中的mix方法可以在这里帮助我?Ui,非常感谢。我会在接下来的几天里试试这个。非常感谢。
for (c = 0; c < bytesPerSample; c++) {
    *(buffer+(currentSample * bytesPerSample) + c)=(*(buffer+(currentSample * bytesPerSample) + c)+*(noise_buffer+((samplesWritten%SAMPLING_RATE)) + c)) / 2;
}
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>

#define SAMPLING_RATE 44100

int remap_level_to_signed_16_bit(float v)
{
  if (v >= 1)
    return 32767;

  if (v <= -1)
    return -32767;

  return v * 32767;
}

void generate_freq(int *buffer, size_t count, float volume, float freq)
{
  size_t pos; // sample number we're on

  for (pos = 0; pos < count; pos++) {
    float a = 2 * 3.14159f * freq * pos / SAMPLING_RATE;
    float v = sin(a) * volume;
    // convert from [-1.0,1.0] to [-32767,32767]:
    buffer[pos] = remap_level_to_signed_16_bit(v);
  }
}

void generate_noise(int *buffer, size_t count, float volume)
{
  size_t pos; // sample number we're on

  for (pos = 0; pos < count; pos++) {
    // random number [-1.0,1.0]
    float v = (rand() - RAND_MAX / 2.0f) * 2 / RAND_MAX * volume;
    // convert from [-1.0,1.0] to [-32767,32767]:
    buffer[pos] = remap_level_to_signed_16_bit(v);
  }
}

int add_two_16_bit_samples(int a, int b)
{
  int sum;

  // add a and b avoiding overflow
  if (a >= 0 && b >= 0) {
    if (a > INT_MAX - b) // mathematically equivalent to if (a + b > INT_MAX)
      sum = INT_MAX; // limit sum at INT_MAX if overflow
    else
      sum = a + b;
  } else if (a < 0 && b < 0) {
    if (a < INT_MIN - b) // mathematically equivalent to if (a + b < INT_MIN)
      sum = INT_MIN; // limit sum at INT_MIN if overflow
    else
      sum = a + b;
  } else {
    sum = a + b;
  }

  // limit sum to [-32767,32767]
  if (sum > 32767)
    sum = 32767;

  if (sum < -32767)
    sum = -32767;

  return sum;
}

void add_16_bit_samples(int *destination, const int* source, size_t count)
{
  for (; count--; destination++, source++) {
    *destination = add_two_16_bit_samples(*destination, *source);
  }
}

int save_16_bit_samples(const char* name, int* buf, size_t count, int stereo)
{
  FILE* f = fopen(name, "wb");
  int res = -1; // failure by default

  if (f != NULL) {

    while (count) {
      // convert sample to 2's complement unsigned representation
      unsigned v = *buf++;

      // separate it into 8-bit parts
      unsigned char c[2];
      c[0] = v & 0xFF; // LSB
      c[1] = (v >> 8) & 0xFF; // MSB

      // save it as little endian
      if (fwrite(c, 1, 2, f) != 2)
        break;

      // do once more if stereo
      if (stereo)
        if (fwrite(c, 1, 2, f) != 2)
          break;

      count--;
    }

    if (count == 0)
      res = 0; // success if all samples written out

    fclose(f);
  }

  return res;
}

int main(void)
{
  int* buf_440 = malloc(SAMPLING_RATE * sizeof(int));
  int* buf_noise = malloc(SAMPLING_RATE * sizeof(int));

  if (buf_440 == NULL || buf_noise == NULL) {
    printf("failed to allocate memory for samples\n");
    return EXIT_FAILURE;
  }

  generate_freq(buf_440, SAMPLING_RATE, 0.1f/*volume*/, 440.0f/*freq*/);
  generate_noise(buf_noise, SAMPLING_RATE, 0.01f/*volume*/);

  add_16_bit_samples(buf_440, buf_noise, SAMPLING_RATE);

  if (save_16_bit_samples("440noise.pcm", buf_440, SAMPLING_RATE, 1/*stereo*/)) {
    printf("failed to save samples to file\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}