周波数の異なる sine curve を滑らかにつなぐ
サインカーブつなぐテスト。
Pygame での波形作成のテストが目的なのでこの範囲では不要な array なんて使っちゃってますが気にしないように。
(Python 2.5 + Pygame 1.8)
from __future__ import division import math import array import random import pygame from pygame.locals import * FULLSCREEN = False # True にするとフルスクリーン表示 WIDTH, HEIGHT = 50 * 13, 200 # 表示する画面のサイズ BG_COLOR = 0, 0, 50 # 背景色 BASE_FREQUENCY = 1 # 基本周波数(Hz) PYGAME_FREQUENCY = 100 # 1Hz の長さ def sins(frequency, start, length): ## volume = BASE_FREQUENCY / frequency volume = 1 datalen =int(PYGAME_FREQUENCY * length) data = array.array('h', [0] * 2 * datalen) a = math.pi * 2 * frequency / PYGAME_FREQUENCY start_a = start vol = min(32767, 32767 * volume) for i in range(datalen): data[i * 2] = data[i * 2 + 1] = int(math.sin(a * i + start_a) * vol) return data, (a * datalen + start_a) % (math.pi * 2) def main(): screen = pygame.display.set_mode( (WIDTH, HEIGHT), (pygame.FULLSCREEN | pygame.HWSURFACE | pygame.DOUBLEBUF) if FULLSCREEN else 0) log_base = math.log(BASE_FREQUENCY, 2) while True: screen.fill(BG_COLOR) for x in range(0, WIDTH, 50): pygame.draw.line( screen, (0, 0, 255), (x, 0), (x, HEIGHT - 1), 1) xp = 0 alpha = 0 for note in range(13): ## frequency = 2 ** (log_base + note / 12) frequency = 2 ** (log_base + random.random()) data, alpha = sins(frequency, alpha, .5) h = HEIGHT // 2 pygame.draw.lines( screen, ((1 - note % 2) * 255, (note % 2) * 255, 200), False, [(x + xp, data[x * 2] * h // 32767 + h) for x in range(0, len(data) // 2)], 1) xp += 50 pygame.display.flip() break_while = False while not break_while: pygame.time.wait(100) for event in pygame.event.get(): if event.type in (KEYDOWN, QUIT): return elif event.type == MOUSEBUTTONDOWN: break_while = True break if __name__=='__main__': pygame.init() try: main() finally: pygame.quit() # 好きに流用してください。
マウスクリックで別パターン描画、何かのキーを押すと終了です。
## volume = BASE_FREQUENCY / frequency volume = 1
ここんところ生かすと波形は合ってもボリュームの差で上手くつながらないのが悩みどころ。