C 如何解决生成音乐的无限循环?

C 如何解决生成音乐的无限循环?,c,audio,while-loop,infinite-loop,C,Audio,While Loop,Infinite Loop,我有一个程序,我想创建一个随机生成的音乐条(4拍一条,使用C大调音阶)。然而,我在理解数学方面遇到了困难,我的do-while循环不断溢出,在条上创建了4个以上的注释,这是我想要避免的 我使用的是我的导师创建的aServe,但它基本上会打开一个振荡器的流,播放我所评论的参数 /* Program for randomly written bar of 4/4 in C Major */ #include "aservelibs/aservelib.h" #include <stdio.h

我有一个程序,我想创建一个随机生成的音乐条(4拍一条,使用C大调音阶)。然而,我在理解数学方面遇到了困难,我的do-while循环不断溢出,在条上创建了4个以上的注释,这是我想要避免的

我使用的是我的导师创建的aServe,但它基本上会打开一个振荡器的流,播放我所评论的参数

/* Program for randomly written bar of 4/4 in C Major */

#include "aservelibs/aservelib.h"
#include <stdio.h>
#include <stdlib.h>

//macros
#define SEMIBREVE       (1.0)
#define MINIM           (1.0/2)
#define CROTCHET        (1.0/4)
#define QUAVER          (1.0/8)
#define SEMIQUAVER      (1.0/16)
#define DEMISEMIQUAVER  (1.0/32)

#define C   (261.63)
#define D   (293.66)
#define E   (329.63)
#define F   (349.23)
#define G   (391.99)
#define A   (440.00)
#define B   (493.88)

int millisec(int bpm, double note) {
    return (int)(
                 60      /* seconds */
                 * 1000  /* milliseconds per second */
                 * 4     /* crotchets per semibreve */
                 * note
                 / bpm
                 );
}

int main()
{
    int bpm = 120; //BPM Value
    double Length[] = {SEMIBREVE, MINIM, CROTCHET, QUAVER, SEMIQUAVER, DEMISEMIQUAVER}; //Array of Note Lengths
    double Pitch[] = {C, D, E,F, G, A, B}; //Array of CMajor Scale Freq

    int randLength = (rand() % 6); //random positions for note length
    int randPitch = ( rand() % 7); //random positions for note pitch
    double barTotal = 0; //amount of bar currently completed

    do {
        if(barTotal < 1) //if bar total is smaller than 1
        {
            barTotal = Length[randLength] + barTotal; //add note to total

            aserveOscillator(0, Pitch[randPitch], 1, 2); //Starts stream to oscialltor
                //aserveOscillator(Index,Frequency,Amplitude,WaveType);
            aserveSleep(millisec(bpm, Length[randLength])); //play the notes for the length of time specified in milliseconds

            randLength = (rand() % 6); //prepare next random note
            randPitch = (rand() % 7); //prepare next random pitch

            //Output
            printf("Note: ");
            printf("%lf", Pitch[randPitch]);
            printf("\n For: ");
            printf("%lf", Length[millisec(bpm,randLength)]);
            printf("\n With Bar Total: ");
            printf("%lf", barTotal);
            printf("\n\n");
        }
        else
        {
            if(barTotal != 1) //if bar total is bigger than 4
            {
                randLength = (rand() % 6); //try another number
            }
        }

    } while (barTotal != 1); //will stop once reaches 4

    return 0;
}
/*C大调中随机写入的4/4条的程序*/
#包括“aservelibs/aservelib.h”
#包括
#包括
//宏
#定义SEMIBREVE(1.0)
#定义最小值(1.0/2)
#定义交叉点(1.0/4)
#定义QUAVER(1.0/8)
#定义SEMIQUAVER(1.0/16)
#定义Miquaver(1.0/32)
#定义C(261.63)
#定义D(293.66)
#定义E(329.63)
#定义F(349.23)
#定义G(391.99)
#定义A(440.00)
#定义B(493.88)
整数毫秒(整数bpm,双音符){
返回(整数)(
60/*秒*/
*每秒1000/*毫秒*/
*每半短边4/*个胯部*/
*注
/bpm
);
}
int main()
{
int bpm=120;//bpm值
双长度[]={SEMIBREVE,MINIM,CROTCHET,QUAVER,SEMIQUAVER,distisemiquaver};//音符长度数组
双节距[]={C,D,E,F,G,A,B};//CMajor Scale Freq数组
int randLength=(rand()%6);//注释长度的随机位置
int randPitch=(rand()%7);//音符音高的随机位置
double barTotal=0;//当前完成的条数
做{
if(barTotal<1)//如果条总数小于1
{
barTotal=长度[randLength]+barTotal;//将注释添加到总计中
AserveSocator(0,俯仰[randPitch],1,2);//开始流到振荡器
//A振荡器(指数、频率、振幅、波型);
aserveSleep(毫秒(bpm,Length[randLength]);//播放音符的时间长度以毫秒为单位
randLength=(rand()%6);//准备下一张随机便笺
randPitch=(rand()%7);//准备下一个随机音高
//输出
printf(注:);
printf(“%lf”,音高[randPitch]);
printf(“\n表示:”);
printf(“%lf”,长度[毫秒(bpm,randLength)];
printf(“\n带条总数:”);
printf(“%lf”,巴托塔);
printf(“\n\n”);
}
其他的
{
if(barTotal!=1)//如果条总数大于4
{
randLength=(rand()%6);//请尝试其他数字
}
}
}while(barTotal!=1);//将在达到4时停止
返回0;
}

考虑以不同的方式思考问题。把一个条想象成“n”槽,其中n是你拥有的最细粒度的音符类型。因此,在您的例子中,一个条是一组32个插槽。不要将数字表示为分数,而是使用整数类型来显示每个“槽”的数量。因此,一个DemisiQuaver占用1个插槽,可以用int表示,而不是(1.0/32.0),这会带来一些潜在的丑陋问题

完成此操作后,解决方案将更加简单:

1) 当前栏中还剩下多少个插槽? 2) 从小于剩余插槽的注释池中随机选择一个注释 3) 重新计算添加新便笺后剩余的空间 4) 如果剩余的房间为零,则转到下一个酒吧

下面是适应这种新方法的代码。虽然没有完全测试,但它应该能够避免迄今为止讨论的大多数(如果不是全部的话)陷阱

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//macros
#define SEMIBREVE       (32)
#define MINIM           (16)
#define CROTCHET        (8)
#define QUAVER          (4)
#define SEMIQUAVER      (2)
#define DEMISEMIQUAVER  (1)

#define C   (261.63)
#define D   (293.66)
#define E   (329.63)
#define F   (349.23)
#define G   (391.99)
#define A   (440.00)
#define B   (493.88)

int GetMaxIndex(int remainingLength)
{
    // Returns the largest upper bound of the Length array that
    // should be considered based on how much room remains in 
    // the current bar.
    int result;
    if(remainingLength == 32) result = 5;
    if(remainingLength < 32) result = 4;
    if(remainingLength < 16) result = 3;
    if(remainingLength < 8) result = 2;
    if(remainingLength < 4) result = 1;
    if(remainingLength < 2) result = 0;
    return result;

}

int main()
{
    double Pitch[] = {C, D, E,F, G, A, B}; //Array of CMajor Scale Freq

    int bpm = 120; //BPM Value
    int Length[] = {DEMISEMIQUAVER, SEMIQUAVER, QUAVER, CROTCHET, MINIM, SEMIBREVE}; //Array of Note Lengths
    char* Labels[] = {"DEMISEMIQUAVER (Thirty Second)", "SEMIQUAVER (Sixteenth)", "QUAVER (Eighth)", "CROTCHET (Quarter)", "MINIM (Half)", "SEMIBREVE (Whole)"}; 
    int remainingThisBar;
    int barsToGenerate = 4;

    int randLength = (rand() % 6); //random positions for note length
    int randPitch; //random positions for note pitch
    int maxIndex;
    int randIndex;

    srand(time(NULL));

    for(int barNumber = 0; barNumber < barsToGenerate; barNumber++)
    {
        printf("Beginning bar: %i\n", barNumber);
        remainingThisBar = 32;

        while(remainingThisBar > 0)
        {
            maxIndex = GetMaxIndex(remainingThisBar);  // What is the biggest note index we still have room for?
            randIndex = maxIndex == 0 ? 0 : (rand() % maxIndex); // Get a random note between 0 and maxIndex

            randPitch = ( rand() % 7);      // Random positions for note pitch
            randLength = Length[randIndex]; // Length in 32nds
            remainingThisBar -= randLength; 

            // Output
            printf("\tNote: %s @ %f\n", Labels[randIndex], Pitch[randPitch]);
            printf("\t32nds remaining in bar: %i\n", remainingThisBar);
            printf("\n");

            /* TODO - Output note via aServe*/
        }
    }
}
#包括“stdafx.h”
#包括
#包括
#包括
//宏
#定义半隐式(32)
#定义最小值(16)
#定义交叉点(8)
#定义QUAVER(4)
#定义SEMIQUAVER(2)
#定义Miquaver(1)
#定义C(261.63)
#定义D(293.66)
#定义E(329.63)
#定义F(349.23)
#定义G(391.99)
#定义A(440.00)
#定义B(493.88)
int GetMaxIndex(int remainingLength)
{
//返回指定的长度数组的最大上限
//应根据剩余空间的大小来考虑
//当前栏。
int结果;
如果(剩余长度==32)结果=5;
如果(剩余长度<32)结果=4;
如果(剩余长度<16)结果=3;
如果(剩余长度<8)结果=2;
如果(剩余长度<4)结果=1;
如果(剩余长度<2)结果=0;
返回结果;
}
int main()
{
双节距[]={C,D,E,F,G,A,B};//CMajor Scale Freq数组
int bpm=120;//bpm值
int Length[]={miquaver,SEMIQUAVER,QUAVER,CROTCHET,MINIM,SEMIBREVE};//音符长度数组
字符*标签[]={“第三十二个”、“第十六个”、“第八个”、“四分之一个”、“最小(一半)”、“半个(整个)”;
在该条中保留整数;
int barsToGenerate=4;
int randLength=(rand()%6);//注释长度的随机位置
int randPitch;//音符音高的随机位置
int-maxIndex;
国际贸易指数;
srand(时间(空));
for(int-barNumber=0;barNumber0)
{
maxIndex=GetMaxIndex(保留此条);//我们还有空间容纳的最大音符索引是什么?
randIndex=maxIndex==0?0:(rand()%maxIndex);//获取一个介于0和maxIndex之间的随机音符
randPitch=(rand()%7);//音符音高的随机位置
randLength=长度[randIndex];//长度(单位:32nds)
保留该条-=随机长度;
//输出
printf(“\t注意:%s@%f\n”,标签[randIndex],音高[randPitch]);
printf(“\t32nds剩余在条中:%i\n”,剩余在该条中);
printf(“\n”);
/*待办事项-输出说明