为什么我的音频功能保持循环而不是一直运行?

时间:2015-03-17 18:45:23

标签: c function audio

我的代码与我的“播放”功能不同。我正在尝试让程序读取“记录”功能创建的.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;
}

4 个答案:

答案 0 :(得分:2)

   fclose(file);
   return *file;

如果您关闭它,则无法再使用它。如果您希望以后仍然使用它(请执行此操作),请不要关闭file

答案 1 :(得分: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. 您正在counter中的所有三个0块中将if设置为maincounter的值何时为16才能满足do-while循环的退出条件?这是疏忽吗?

  4. play()的实施中,您有:

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

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

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

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

    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");
    }
    
  5. 关注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");
    }
    

答案 2 :(得分:1)

您永远不会像以下一样调用播放功能:

else if (user == 'p' || user == 'P')
{
   ...
   play ();
}

答案 3 :(得分:0)

在你第二次打电话给fopen后可能会这样做:

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

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

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

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