【问题标题】: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;
}

【问题讨论】:

    标签: c function audio


    【解决方案1】:
       fclose(file);
       return *file;
    

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

    【讨论】:

      【解决方案2】:

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

      1. 当用户输入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()

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

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

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

         play();
        

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

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

      4. 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 {
              ...
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-31
            • 1970-01-01
            • 2020-05-17
            • 2017-07-06
            • 1970-01-01
            • 2021-06-04
            相关资源
            最近更新 更多