2016-12-12 14 views
8

मैं एलईडी के 8 स्ट्रिप्स के साथ घर निर्मित स्पेक्ट्रम विश्लेषक बनाने की कोशिश कर रहा हूं।स्पेक्ट्रम विश्लेषक के लिए एफएफटी डेटा का उपयोग कैसे करें

जिस भाग के साथ मैं संघर्ष कर रहा हूं वह एफएफटी कर रहा है और परिणामों का उपयोग कैसे कर रहा है।

import opc 
import time 
import pyaudio 
import wave 
import sys 
import numpy 
import math 

CHUNK = 1024 

# Gets the pitch from the audio 
def pitch(signal): 
    # NOT SURE IF ANY OF THIS IS CORRECT 
    signal = numpy.fromstring(signal, 'Int16'); 
    print "signal = ", signal 

    testing = numpy.fft.fft(signal) 
    print "testing = ", testing 

wf = wave.open(sys.argv[1], 'rb') 
RATE = wf.getframerate() 
p = pyaudio.PyAudio() # Instantiate PyAudio 

# Open Stream 
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), 
       channels=wf.getnchannels(), 
       rate=wf.getframerate(), 
       output=True) 

# Read data 
data = wf.readframes(CHUNK) 

# Play Stream 
while data != '': 
    stream.write(data) 
    data = wf.readframes(CHUNK) 
    frequency = pitch(data) 
    print "%f frequency" %frequency 

मैं क्या pitch विधि में क्या करना के साथ संघर्ष कर रहा हूँ:

अभी तक यह है कि मैं क्या है। मुझे पता है कि मुझे पास किए गए डेटा पर एफएफटी करने की ज़रूरत है, लेकिन वास्तव में यह सुनिश्चित नहीं है कि इसे कैसे किया जाए।

भी this फ़ंक्शन का उपयोग करना चाहिए?

+2

आप किस बारे में अनिश्चित हैं? दो कार्यों के लिए दस्तावेज़ों को देखो। क्या आपने numpy.fft.fftfreq के लिए दस्तावेज़ पृष्ठ पर उदाहरण देखा था? http://www.dspguide.com/pdfbook.htm एक अच्छा संसाधन है। – wwii

+0

इस पृष्ठ पर उदाहरण लंबाई 8 की एक श्रृंखला दिखाता है। उन्हें 8 की लंबाई कैसे मिली? मेरा हिस्सा आकार 1024 और 2 चैनल है इसलिए मेरी सरणी लंबाई 2048 है। Https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.fftpack.fftfreq.html#scipy.fftpack.fftfreq – Catfish

+0

मैं दो चैनलों को अलग से इलाज करूंगा। 'np.fft.fft()' जटिल मानों की एक सरणी को इसके इनपुट के समान लंबाई लौटाएगा - प्रत्येक मान एक आवृत्ति का प्रतिनिधित्व करता है, जटिल संख्या का पूर्ण मूल्य उस आवृत्ति की परिमाण है, मान का जटिल घटक है इसकी चरण शिफ्ट। 'np.fft.fftfreq()' वास्तविक आवृत्तियों के साथ एक सरणी देता है जो चौकोर परिवर्तन से मूल्य लौटाता है। यदि आप स्पेक्ट्रम 'np.absolute (np.fft.fft (सिग्नल)) प्लॉट करना चाहते हैं तो' ordinate (y मान) और 'np.fft.fftfreq (...)' abscissa (x) होगा । – wwii

उत्तर

3
जिस तरह से np.fft.fft काम करता है, अगर आप 1024 डेटा बिंदुओं का उपयोग आप 512 आवृत्तियों के लिए मूल्य मिलेगा की

(प्लस एक मूल्य शून्य हर्ट्ज, डीसी ऑफसेट)। यदि आप केवल 8 आवृत्तियों चाहते हैं तो आपको इसे 16 डेटा पॉइंट्स फ़ीड करना होगा।

आप 64 के कारक द्वारा नमूनाकरण करके जो भी करना चाहते हैं, वह करने में सक्षम हो सकते हैं - तो 16 नीचे नमूने वाले अंक समय-समतुल्य से 1024 मूल बिंदुओं पर होंगे। मैंने कभी इसकी खोज नहीं की है इसलिए मुझे नहीं पता कि इसमें क्या शामिल है या क्या नुकसान हो सकता है।

आपको कुछ सीखना होगा - The Scientist and Engineer's Guide to Digital Signal Processing वास्तव में एक उत्कृष्ट संसाधन है, कम से कम यह मेरे लिए था।

ध्यान रखें कि एक ऑडियो सीडी। वाव फ़ाइल के लिए नमूना आवृत्ति 44100 हर्ट्ज है - एक 1024 नमूना हिस्सा ध्वनि का केवल 23 एमएस है।

scipy.io.wavfile.read डेटा को आसान बनाता है। [:, 0], और में अन्य स्तंभ 1, डेटा

samp_rate, data = scipy.io.wavfile.read(filename) 

data स्तंभ शून्य में, डेटा में एक चैनल के साथ एक 2-डी numpy सरणी है [:, 1]

matplotlib के specgram और पीएसडी फ़ंक्शंस आपको इच्छित डेटा दे सकता है। आप जो करने की कोशिश कर रहे हैं उसके लिए एक ग्राफिंग एनालॉग होगा।

from matplotlib import pyplot as plt 
import scipy.io.wavfile 
samp_rate, data = scipy.io.wavfile.read(filename) 
Pxx, freqs, bins, im = plt.specgram(data[:1024,0], NFFT = 16, noverlap = 0, Fs = samp_rate) 
plt.show() 
plt.close() 

के बाद से आप किसी भी साजिश कर रही है नहीं कर रहे हैं बस matplolib.mlab.specgram का उपयोग करें।

Pxx, freqs, t = matplolib.mlab.specgram(data[:1024,0], NFFT = 16, noverlap = 0, Fs = samp_rate) 

इसकी वापसी मान (Pxx, freqs, टी),

 - *Pxx*: 2-D array, columns are the periodograms of successive segments 

    - *freqs*: 1-D array of frequencies corresponding to the rows in Pxx 

    - *t*: 1-D array of times corresponding to midpoints of segments. 

Pxx[1:, 0] टी 2 के लिए T0, T1 के लिए Pxx[1:, 1], Pxx[1:, 2] के लिए आवृत्तियों के लिए मूल्यों होगा ... यही वह है जिसे आप अपने प्रदर्शन में खिलाएंगे। आप Pxx[0, :] का उपयोग नहीं करते क्योंकि यह 0 हर्ट्ज के लिए है।

पावर वर्णक्रमीय घनत्व - matplotlib.mlab.psd()


हो सकता है कि एक और रणनीति 8 बैंड करने के लिए नीचे लाने के लिए बड़े हिस्से का उपयोग करें और मूल्यों को सामान्य बनाने में किया जाएगा। फिर आप मूल्यों को आठ खंडों में विभाजित कर सकते हैं और प्रत्येक सेगमेंट का योग प्राप्त कर सकते हैं। मुझे लगता है कि यह मान्य है - शायद केवल बिजली वर्णक्रमीय घनत्व के लिए। sklearn.preprocessing.normalize

w = sklearn.preprocessing.normalize(Pxx[1:,:], norm = 'l1', axis = 0) 

लेकिन तब फिर से, मैं सिर्फ यह सब बना हुआ है।

1

मुझे scipy.io.wavfile.read फ़ंक्शन के बारे में पता नहीं है जो @wwii उनके उत्तर में उल्लेख करता है, लेकिन ऐसा लगता है कि सिग्नल लोडिंग को संभालने के लिए उसका सुझाव है। हालांकि, मैं सिर्फ चौकोर परिवर्तन पर टिप्पणी करना चाहता था।

मुझे क्या लगता है कि आप अपने एलईडी सेटअप के साथ करना चाहते हैं, प्रत्येक 8 फ्रीक्वेंसी बैंड में स्पेक्ट्रा की शक्ति के अनुसार प्रत्येक एलईडी की चमक को बदलना है जिसका आप उपयोग करना चाहते हैं। इस प्रकार, जो मुझे समझ में आया है, वह समय के रूप में शक्ति के रूप में किसी भी तरह से गणना करना है। पहली जटिलता "स्पेक्ट्रल पावर की गणना कैसे करें?"

यह करने के लिए सबसे अच्छा तरीका है numpy.fft.rfft, जो फूरियर गणना करता संकेतों केवल वास्तविक संख्या (नहीं जटिल संख्या) होती हैं, के बदलने के साथ है। दूसरी ओर, फ़ंक्शन numpy.fft.fft एक सामान्य उद्देश्य फ़ंक्शन है जो जटिल संख्याओं के साथ संकेतों के लिए तेज़ चौकोर परिवर्तन की गणना कर सकता है। वैचारिक अंतर यह है कि numpy.fft.fft का उपयोग यात्रा तरंगों और उनके प्रचार दिशा का अध्ययन करने के लिए किया जा सकता है। ऐसा इसलिए देखा जाता है क्योंकि लौटा आयाम positive or negative frequencies से मेल खाता है जो इंगित करता है कि लहर कैसे यात्रा करती है। numpy.fft.rfft वास्तविक मूल्यवान आवृत्तियों के लिए आयाम उत्पन्न करता है जैसा कि numpy.fft.rfftfreq में देखा गया है, जो आपको चाहिए।

अंतिम मुद्दा स्पेक्ट्रल पावर की गणना करने के लिए उचित आवृत्ति बैंड चुनना है। मानव कान में एक विशाल आवृत्ति प्रतिक्रिया सीमा होती है और प्रत्येक बैंड की चौड़ाई बहुत भिन्न होती है, कम आवृत्ति बैंड बहुत संकीर्ण होता है और उच्च आवृत्ति बैंड बहुत व्यापक होता है। चारों ओर Googling, मैं this अच्छा संसाधन है कि 7 प्रासंगिक आवृत्ति बैंड

को परिभाषित करता है पाया
  1. उप-बास: 20 60 हर्ट्ज
  2. बास के लिए: 60 250 हर्ट्ज के लिए
  3. कम मध्यश्रेणी: 250 से 500 हर्ट्ज
  4. मध्यम-श्रेणी: 500 हर्ट्ज 2 kHz तक
  5. ऊपरी मध्यश्रेणी: 4 किलो हर्ट्ज के लिए 2
  6. उपस्थिति: 4 से 6
  7. दीप्ति को kHz: 6 से 20 किलो हर्ट्ज
  8. 01,235,

मैं इन बैंडों का उपयोग करने का सुझाव दूंगा, लेकिन ऊपरी मिड्रेंज को 2-3 किलोहर्ट्ज़ और 3-4kHz में विभाजित करता हूं। इस तरह आप अपने 8 एलईडी सेटअप का उपयोग करने में सक्षम होंगे। आप

wf = wave.open(sys.argv[1], 'rb') 
CHUNK = 1024 
RATE = wf.getframerate() 
DT = 1./float(RATE) # time between two successive audio frames 
FFT_FREQS = numpy.fft.nfftfreq(CHUNCK,DT) 
FFT_FREQS_INDS = -numpy.ones_like(FFT_FREQS) 
bands_bounds = [[20,60],  # Sub-bass 
       [60,250],  # Bass 
       [250,500], # Low midrange 
       [500,2000], # Midrange 
       [2000,3000], # Upper midrange 0 
       [3000,4000], # Upper midrange 1 
       [4000,6000], # Presence 
       [6000,20000]] # Brilliance 

for f_ind,freq in enumerate(FFT_FREQS): 
    for led_ind,bounds in enumerate(bands_bounds): 
     if freq<bounds[1] and freq>=bounds[0]: 
      FFT_FREQS_INDS[ind] = led_ind 

# Returns the spectral power in each of the 8 bands assigned to the LEDs 
def pitch(signal): 
    # CONSIDER SWITCHING TO scipy.io.wavfile.read TO GET SIGNAL 
    signal = numpy.fromstring(signal, 'Int16'); 
    amplitude = numpy.fft.rfft(signal.astype(numpy.float)) 
    power = [np.sum(np.abs(amplitude[FFT_FREQS_INDS==led_ind])**2) for led_ind in range(len(bands_bounds))] 
    return power 

कोड के पहले भाग fft आवृत्तियों की गणना करता है और सरणी FFT_FREQS_INDS कि इंगित करता है जो 8 आवृत्ति बैंड के fft आवृत्ति से मेल खाती है करने के लिए निर्माण का उपयोग करने के लिए मैं एक अद्यतन पिच समारोह को अपलोड कर रहा हूँ।फिर, pitch में प्रत्येक बैंड में स्पेक्ट्रा की शक्ति की गणना की जाती है। बेशक, इसे अनुकूलित किया जा सकता है लेकिन मैंने कोड को आत्म-स्पष्टीकरण देने की कोशिश की।

+0

मुझे यह त्रुटि मिलती है: 'अगर freq <सीमाएं [1] और freq> = सीमाएं [0]: इंडेक्स त्रुटि: श्रेणी – Catfish

+0

@catfish ups से सूची अनुक्रमणिका! मेरे पास सीमा सूची में एक टाइपो था। मैंने '' 'के बजाय' -' लिखा था – lucianopaz

संबंधित मुद्दे