gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 23:43:29 25 4
gpt4 key购买 nike

我有一个程序,我想创建一个随机生成的音乐小节(一个小节 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;
}

最佳答案

考虑以不同的方式思考问题。将小节想象成“n”槽,其中 n 是您拥有的最精细的音符类型。所以在你的情况下,一个酒吧是一组 32 个插槽。不要将您的数字表示为分数,而是使用整数类型来显示每个“插槽”中有多少个。因此,一个 DEMISEMIQUAVER 占用 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*/
}
}
}

关于c - 如何解决生成音乐的无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39751283/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com