Créer un fichier wav à partir du shader GLSL en utilisant python3

J'ai expérimenté avec le shader musical, mais il est de plus en plus difficile de le développer avec webGL car cela ne fonctionne pas. J'ai donc créé un script pour créer un fichier wav à partir du shader GLSL en utilisant python. Je pense qu'il sera plus facile d'ajuster les paramètres détaillés si python est impliqué.

Les choses nécessaires

Veuillez installer pyopengl et pyaudio avec pip. Si ça ne marche pas http://www.lfd.uci.edu/~gohlke/pythonlibs/ Le téléchargement du package à partir d'ici fonctionne généralement.

C'est le script

L'explication ici est difficile, veuillez donc l'utiliser comme bibliothèque. Le taux d'échantillonnage est réglé sur 48000. Si vous aimez la différence, veuillez la corriger de manière appropriée.

from OpenGL.GL import *
from OpenGL.WGL import *
from ctypes import *
import numpy
import pyaudio
import wave
import array

def shader2data(duration, src): #Temps de sortie, source de musique de shader
    sampleRate = 48000
    numSamples  = duration*sampleRate
    numSamplesC = numSamples*2
    samples = (c_float * numSamplesC)()
    hWnd = windll.user32.CreateWindowExA(0,0xC018,0,0,0,0,0,0,0,0,0,0)
    hDC = windll.user32.GetDC(hWnd)
    pfd = PIXELFORMATDESCRIPTOR(0,1,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0)
    SetPixelFormat(hDC,ChoosePixelFormat(hDC, pfd), pfd)
    hGLrc = wglCreateContext(hDC)
    wglMakeCurrent(hDC, hGLrc)
    program = glCreateProgram()
    shader = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(shader, src)
    glCompileShader(shader)
    if glGetShaderiv(shader, GL_COMPILE_STATUS) != GL_TRUE:
      raise RuntimeError(glGetShaderInfoLog(shader).decode())
    glAttachShader(program, shader)
    outs =  cast((c_char_p*1)(b"gain"), POINTER(POINTER(c_char)))
    glTransformFeedbackVaryings(program, 1, outs, GL_INTERLEAVED_ATTRIBS)
    glLinkProgram(program)
    glUseProgram(program)
    vbo = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    glBufferData(GL_ARRAY_BUFFER, sizeof(samples), None, GL_STATIC_DRAW)
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo)
    glUniform1f(glGetUniformLocation(program, "sampleRate"), sampleRate)
    glEnable(GL_RASTERIZER_DISCARD)
    glBeginTransformFeedback(GL_POINTS)
    glDrawArrays(GL_POINTS, 0, numSamples)
    glEndTransformFeedback()
    glDisable(GL_RASTERIZER_DISCARD)
    glGetBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(samples), byref(samples))
    wglMakeCurrent(0, 0);
    wglDeleteContext(hGLrc);
    windll.user32.ReleaseDC(hWnd, hDC);
    windll.user32.PostQuitMessage(0);
    return numpy.frombuffer(samples, dtype=numpy.float32)

def writeWav(filename, data):    
    sampleRate = 48000
    w = wave.Wave_write(filename)
    w.setnchannels(2)
    w.setsampwidth(2)
    w.setframerate(sampleRate)
    w.writeframes(array.array('h', data*32767).tobytes())
    w.close()

def readWav(filename): 
    w = wave.open(filename, 'rb')
    print("params  :", w.getparams())
    print("duration:", w.getnframes() / w.getframerate(), "sec")
    p = pyaudio.PyAudio()
    stream = p.open(format=p.get_format_from_width(w.getsampwidth()),
                channels=w.getnchannels(),
                rate=w.getframerate(),
                output=True)
    stream.write(w.readframes(w.getnframes()))
    stream.close()
    p.terminate()

def playSound(data):    
    sampleRate = 48000
    p = pyaudio.PyAudio()
    stream = p.open(rate=sampleRate, channels=2, format=pyaudio.paFloat32, output=True)
    stream.write(array.array('f', data).tobytes())
    stream.close()
    p.terminate()

Règles simples pour écrire un shader

Il utilise le même nom de fonction et le même nom d'argument que mainSound (), qui est la fonction principale du shader musical de shadertoy. Ainsi, vous pouvez copier et coller le shader de musique shadertoy pour cette partie. Ne changez pas d'autre uniforme, hors, principal (), etc.

src = """
#version 300 es

out vec2 gain; 
uniform float sampleRate;    

vec2 mainSound( float time )
{
  return vec2(sin(6.2831*440.0*time)); ;
}

void main() {
  float time = float(gl_VertexID) / sampleRate;
  gain =mainSound(time); 
}
"""

C'est la source du shader. Si vous mettez this et shader2data (duration, src) avec l'heure de sortie comme argument, des exemples de données seront générés. Entrez ces exemples de données et le nom de fichier dans writeWav (nom de fichier, données) pour créer un fichier wav. Vous pouvez entendre le son avec readWav (nom de fichier). Si vous souhaitez produire le son tel quel sans créer de fichier, utilisez playSound (data).

data = shader2data(2,src)
filename = "output.wav"
writeWav(filename, data)
readWav(filename)
playSound(data)

Je l'utilise comme ça.

finalement

Je ne pense pas qu'il y ait de demande, mais j'ai écrit un article qui se double d'un mémorandum. J'ai mis le fichier ipython ici. https://gist.github.com/gaziya/e5d40b0df1a65510af81b124c4ecf4cc

Recommended Posts

Créer un fichier wav à partir du shader GLSL en utilisant python3
Créer un fichier deb à partir d'un package python
Créer un fichier GIF en utilisant Pillow en Python
Exécutez des fichiers Python à partir de HTML en utilisant Django
Créez un fichier MIDI en Python en utilisant pretty_midi
Créez un fichier image à l'aide de PIL (Python Imaging Library).
Créez votre premier fichier GDSII en Python en utilisant gdspy
Script Python qui crée un fichier JSON à partir d'un fichier CSV
Aplatir à l'aide du rendement Python de
Créer des tickets JIRA en utilisant Python
Exécuter le script Python à partir du fichier de commandes
Utilisation de Rstan de Python avec PypeR
Remarques sur l'utilisation de MeCab depuis Python
Utiliser Cloud Storage depuis Python3 (Introduction)
Extraire le fichier targz en utilisant python
Exécutez Ansible à partir de Python à l'aide de l'API
Précautions lors de l'utilisation de phantomjs de python
Accéder aux feuilles de calcul à partir de Python à l'aide d'OAuth 2.0
Accéder aux nœuds de shader de Blender depuis Python
[Python] Opération de fichier utilisant l'instruction if
Essayez d'utiliser Amazon DynamoDB à partir de Python
De Python à l'utilisation de MeCab (et CaboCha)
Créez wordcloud à partir de votre tweet avec python3
Utilisez boto pour télécharger le fichier depuis S3.
Créez rapidement un fichier Excel avec Python #python
Créez un outil qui secoue automatiquement furigana avec html en utilisant Mecab de Python3
[Python] Créer un environnement Batch à l'aide d'AWS-CDK
J'ai essayé d'utiliser l'API UnityCloudBuild de Python
Créer un fichier Excel avec Python + matrice de similarité
[GPS] Créer un fichier kml avec Python
Créer un bloc de données à partir d'Excel à l'aide de pandas
[Hyperledger Iroha] Créez un compte à l'aide de la bibliothèque Python
Modifier Excel à partir de Python pour créer un tableau croisé dynamique
[Python] Fractionner un gros fichier Flask en utilisant Blueprint
Créer un tableau C à partir d'une feuille Python> Excel
Importer un fichier Excel depuis Python (enregistré dans DB)
[Pandas Python] Créer un DataFrame vide à partir d'un DataFrame existant
Je souhaite envoyer un e-mail depuis Gmail en utilisant Python.
Du dessin de fichier au graphique en Python. Élémentaire élémentaire
Comment créer un fichier JSON en Python
Créer une nouvelle tâche Todoist à partir d'un script Python
[python] Créer une table de pandas DataFrame vers postgres
Créer un arbre phylogénétique à partir de Biopyton en utilisant ClustalW2
Créer des données d'imprimante 3D (fichier STL) à l'aide de CadQuery
Créer une carte Web en utilisant Python et GDAL
J'ai essayé de lire un fichier CSV en utilisant Python
Créer un arbre de décision à partir de 0 avec Python (1. Présentation)
Créer un objet datetime à partir d'une chaîne en Python (Python 3.3)
Charger des images à partir d'une URL à l'aide de Pillow dans Python 3
Créer un fichier au format Photoshop (.psd) avec python
Lire ligne par ligne à partir d'un fichier avec Python
Exécutez des scripts Python à partir d'Excel (en utilisant xlwings)
Fichier python de script
Commencez à utiliser Python
sql à sql