为啥我的音频功能一直循环而不是一直运行?

Posted

技术标签:

【中文标题】为啥我的音频功能一直循环而不是一直运行?【英文标题】:Why does my audio function keep looping instead of running all the way through?为什么我的音频功能一直循环而不是一直运行? 【发布时间】:2015-03-17 18:45:22 【问题描述】:

我的代码与我的“播放”功能不同。我试图让程序读取由“记录”功能创建的 .txt 文件并播放笔记。

不幸的是,当用户按下 P 来播放他们录制的音符时,它只是不断弹出相同的菜单,而不是前进到程序的下一步。

#include "aservelibs/aservelib.h"
#include <stdio.h>
#include <math.h>
#include <string.h>

float mtof(int note, float frequency);
FILE play(void);
FILE record(void);
FILE record2(void);

int main()

   FILE *textFilePointer;
   FILE *textFilePointer2;
   int counter = 0;
   char user;

   do
   
      printf("Press A to Record 1st Melody (A), B to Record 2nd Melody (B)\nP to Play Melodies (P):");
      scanf(" %c", &user);

      if (user == 'a' || user == 'A')
      
         textFilePointer = fopen("/Users/Luke/Desktop/midinotes1.txt", "w");
         *textFilePointer = record();
         counter = 0;
      

      else if (user == 'b' || user == 'B')
      
         textFilePointer2 = fopen("/Users/Luke/Desktop/midinotes2.txt", "w");
         *textFilePointer2 = record2();
         counter = 0;
      

      else if (user == 'p' || user == 'P')
      
         textFilePointer = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
         textFilePointer2 = fopen("/Users/Luke/Desktop/midinotes2.txt", "r");
         counter = 0;
      
   
   while(counter < 16);


float mtof(int note, float frequency)

   frequency = 440.0 * pow(2, (note-69) / 12.0);
   printf("%d\n", note);
   return frequency;


FILE play(void)

   FILE*file;
   file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
   file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");

   do 

      int note = aserveGetNote();
      int velocity = aserveGetVelocity();
      fscanf(file, "%d, %d\n", &note, &velocity);
      int frequency = mtof(note, frequency);
      aserveOscillator(0, frequency, 1.0, 0);
      aserveSleep(500);
    while (feof(file) == 0);

   fclose(file);
   return *file;


FILE record(void)

   int counter;
   FILE*file;
   file = fopen("/Users/Luke/Desktop/midinotes1.txt", "w");

   do
   

      int note = aserveGetNote();
      int velocity = aserveGetVelocity();
      if (velocity > 0)
      
         fprintf(file, "%d, %d\n", note, velocity);
         counter++;
      


    while (counter < 16);
   fclose(file);
   return *file;


FILE record2(void)

   int counter;
   FILE*file;
   file = fopen("/Users/Luke/Desktop/midinotes2.txt", "w");

   do
   

      int note = aserveGetNote();
      int velocity = aserveGetVelocity();
      if (velocity > 0)
      
         fprintf(file, "%d, %d\n", note, velocity);
         counter++;
      


    while (counter < 16);
   fclose(file);
   return *file;

【问题讨论】:

【参考方案1】:
   fclose(file);
   return *file;

如果您关闭它,您将无法再使用它。如果您希望以后仍然使用它(您会这样做),请不要关闭 file

【讨论】:

【参考方案2】:

我在您的程序中看到的问题

    当用户输入Aa时,你执行:

     textFilePointer = fopen("/Users/Luke/Desktop/midinotes1.txt", "w");
     *textFilePointer = record();
     counter = 0;
    

    录制到"/Users/Luke/Desktop/midinotes1.txt" 的代码已经硬编码在record() 中。这里不需要在同一个文件上使用fopen()

    record() 不需要返回 FILE。顺便说一句,使用FILE 作为返回类型似乎很奇怪。我认为该标准甚至不支持使用FILE。使用FILE* 作为参数和返回值是我所看到的。

    同样的事情也适用于record2()

    当用户输入pP时,你执行:

     textFilePointer = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
     textFilePointer2 = fopen("/Users/Luke/Desktop/midinotes2.txt", "r");
     counter = 0;
    

    这里没有给play() 的电话。当您将代码转录到此处发布时,可能会丢失。就算加一行

     play();
    

    那里,这里不需要使用fopen()play() 已经打开文件进行播放。此外,您多次打开文件而不使用它们或关闭它们。

    您在main 的所有三个if 块中将counter 设置为0counter 的值何时为 16 以满足 do-while 循环的退出标准?这是疏忽吗?

    play()的实现中,你有:

    file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
    file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
    

    看起来不对。您在同一文件上调用 fopen 两次。当函数返回时,您将留下一个未使用并打开的FILE*

    第二个文件永远不会播放。

    我将建议创建一个辅助函数playFile(),它可以播放给定文件的内容。然后,从play() 呼叫playFile() 两次。这是伪代码:

    void playFile(char const* file)
    
       FILE* file = fopen(file, "r);
    
       if ( file == NULL )
       
          // deal with error.
       
       else
       
          // Your code to play the contents.
    
          // Close the file
          fclose(file);
       
    
    
    void play()
    
       playFile("/Users/Luke/Desktop/midinotes1.txt");
       playFile("/Users/Luke/Desktop/midinotes2.txt");
    
    

关注the DRY principle

我将建议创建一个函数recordToFile(),它具有record()record2() 的公共代码,然后使用正确的参数从record()record2() 调用它。

void recordToFile(char const* file)

   int counter;
   FILE* file = fopen(file, "w");
   if ( file == NULL )
   
      // Deal with error
   
   else
   
      // Your code to record to the file.

      // Close the file
      fclose(file);
   


void record(void)

   recordToFile("/Users/Luke/Desktop/midinotes1.txt");


void record2(void)

   recordToFile("/Users/Luke/Desktop/midinotes2.txt");

【讨论】:

【参考方案3】:

你永远不会像这样调用 play 函数:

else if (user == 'p' || user == 'P')

   ...
   play ();

【讨论】:

【参考方案4】:

可能在您第二次调用 fopen 之后:

   file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
   file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");

FILE * file 将无效。至少,它们是多余的。 您应该删除其中一行。

另外,在使用之前检查file是否有效:

file = fopen("/Users/Luke/Desktop/midinotes1.txt", "r");
if(file) //if fopen fails, file == NULL

    do 
    ...

【讨论】:

以上是关于为啥我的音频功能一直循环而不是一直运行?的主要内容,如果未能解决你的问题,请参考以下文章

运行相同命令时音频机器人离开频道

为啥我的 HTML5 音频不会循环播放?

HTML5 音频循环

为啥这种音频代码循环使用如此多的 CPU/内存?

合并背景音频文件

为啥 Safari Mobile 中无法播放网络音频 api 振荡器?