yufii commited on
Commit
63b0076
·
verified ·
1 Parent(s): 8378bcb

Upload 11 files

Browse files
Files changed (11) hide show
  1. Dockerfile +13 -0
  2. README.md +12 -12
  3. app.py +126 -0
  4. forms.py +9 -0
  5. main.py +85 -0
  6. models.py +56 -0
  7. requirements.txt +13 -0
  8. server.log +0 -0
  9. test.py +51 -0
  10. test_audio.mp3 +0 -0
  11. utils.py +237 -0
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ FROM python:3.11
3
+
4
+ WORKDIR /app
5
+
6
+ COPY . /app
7
+
8
+ RUN pip install --no-cache-dir --upgrade pip && \
9
+ pip install --no-cache-dir -r requirements.txt
10
+
11
+ EXPOSE 8000
12
+
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
README.md CHANGED
@@ -1,12 +1,12 @@
1
- ---
2
- title: Speech Defects
3
- emoji: 📈
4
- colorFrom: red
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- short_description: Model api for detecting speech defects for ai challange
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ ---
2
+ title: Speech Model
3
+ emoji: 🏢
4
+ colorFrom: yellow
5
+ colorTo: blue
6
+ sdk: streamlit
7
+ sdk_version: 1.38.0
8
+ app_file: app.py
9
+ pinned: false
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ from contextlib import contextmanager
3
+ from fastapi import FastAPI, File, UploadFile, HTTPException
4
+ from fastapi.responses import JSONResponse
5
+ from fastapi.middleware.cors import CORSMiddleware
6
+ import tempfile
7
+ import os
8
+ import librosa
9
+ import numpy as np
10
+ import keras
11
+ from utils import (
12
+ create_cnn_model,
13
+ get_features,
14
+ extract_features,
15
+ pad_or_trim,
16
+ noise,
17
+ stretch,
18
+ pitch,
19
+ )
20
+
21
+ app = FastAPI(port=8000)
22
+
23
+ # origins = [
24
+ # "http://localhost:3000",
25
+ # "http://127.0.0.1:3000",
26
+ # # Add more origins if needed
27
+ # ]
28
+
29
+ app.add_middleware(
30
+ CORSMiddleware,
31
+ allow_origins=["*"],#origins,
32
+ allow_credentials=True,
33
+ allow_methods=["*"],
34
+ allow_headers=["*"],
35
+ )
36
+
37
+ filepath = os.path.abspath("cnn_1_v6_final_model.h5")
38
+ if not os.path.exists(filepath):
39
+ raise FileNotFoundError(f"Model file not found at {filepath}")
40
+
41
+ model = keras.models.load_model(filepath, compile=False)
42
+ target_shape = (32, 200)
43
+
44
+
45
+ @app.post("/save-audio")
46
+ async def save_audio(file: UploadFile = File(...)):
47
+ if not file.content_type.startswith("audio/"):
48
+ raise HTTPException(status_code=400, detail="Invalid file type")
49
+
50
+ file_path = os.path.join("audio", file.filename)
51
+ os.makedirs("audio", exist_ok=True)
52
+ try:
53
+ with open(file_path, "wb") as f:
54
+ content = await file.read()
55
+ f.write(content)
56
+ return JSONResponse(
57
+ content={"message": "File saved successfully", "filePath": file_path},
58
+ status_code=200,
59
+ )
60
+ except Exception as e:
61
+ return JSONResponse(content={"error": str(e)}, status_code=500)
62
+
63
+
64
+ logging.basicConfig(
65
+ level=logging.INFO,
66
+ filename="server.log",
67
+ filemode="w",
68
+ format="%(asctime)s - %(levelname)s - %(message)s",
69
+ )
70
+
71
+
72
+ @contextmanager
73
+ def temporary_audio_file(audio_bytes):
74
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp_file:
75
+ tmp_file.write(audio_bytes)
76
+ tmp_file.flush() # Make sure data is written to disk
77
+ tmp_filename = tmp_file.name
78
+ try:
79
+ yield tmp_filename
80
+ finally:
81
+ if os.path.exists(tmp_filename):
82
+ os.remove(tmp_filename)
83
+
84
+
85
+ @app.post("/process-audio")
86
+ async def process_audio(audio: UploadFile = File(...)):
87
+ if audio.content_type != "audio/mpeg":
88
+ raise HTTPException(
89
+ status_code=400, detail="Invalid file type. Only MP3 files are supported."
90
+ )
91
+
92
+ try:
93
+ audio_bytes = await audio.read()
94
+ logging.info(
95
+ f"Received audio bytes: {len(audio_bytes)} bytes"
96
+ ) # Log size of audio bytes
97
+ with temporary_audio_file(audio_bytes) as tmp_filename:
98
+ logging.info(f"Temporary file created: {tmp_filename}")
99
+ audio_data, sample_rate = librosa.load(tmp_filename, sr=None)
100
+ logging.info(
101
+ f"Audio loaded: sample rate = {sample_rate}, data shape = {audio_data.shape}"
102
+ )
103
+ if not audio_data.any() or sample_rate == 0:
104
+ raise ValueError("Empty or invalid audio data.")
105
+
106
+ features = extract_features(audio_data, sample_rate)
107
+ logging.info(f"Features extracted: shape = {features.shape}")
108
+ target_shape = (1, model.input_shape[1])
109
+ features = pad_or_trim(features, target_shape[1])
110
+ features = np.expand_dims(features, axis=0)
111
+
112
+ prediction = model.predict(features)
113
+ # Add interpretation of prediction here (e.g., class labels)
114
+ logging.info(f"Prediction: {prediction}")
115
+ return {"prediction": prediction.tolist()}
116
+
117
+ except librosa.util.exceptions.ParameterError as e:
118
+ logging.error(f"Librosa error: {e}")
119
+ raise HTTPException(status_code=400, detail=f"Invalid audio file: {e}")
120
+ except ValueError as e:
121
+ logging.error(f"Value error: {e}")
122
+ raise HTTPException(status_code=400, detail=f"Invalid audio data: {e}")
123
+ except Exception as e:
124
+ logging.exception(f"Error processing audio: {e}") # Log the full traceback
125
+ raise HTTPException(status_code=500, detail="Internal server error")
126
+
forms.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class UserRegistration(BaseModel):
4
+ login: str
5
+ password: str
6
+
7
+ class UserLoginForm(BaseModel):
8
+ login: str
9
+ password: str
main.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ from models import User, Course, connection
3
+ from forms import UserRegistration, UserLoginForm
4
+ from fastapi.responses import JSONResponse
5
+ from utils import create_cnn_model, get_features, extract_features, pad_or_trim, noise, stretch, pitch
6
+ from peewee import *
7
+ import numpy as np
8
+ import tensorflow as tf
9
+ import keras
10
+ import requests
11
+ import io
12
+ import os
13
+
14
+ from fastapi.middleware.cors import CORSMiddleware
15
+
16
+ app = FastAPI()
17
+
18
+ app.add_middleware(
19
+ CORSMiddleware,
20
+ allow_origins=["*"],
21
+ allow_credentials=True,
22
+ allow_methods=["*"],
23
+ allow_headers=["*"],
24
+ )
25
+
26
+ UPLOAD_DIR = 'audio'
27
+ os.makedirs(UPLOAD_DIR, exist_ok=True)
28
+
29
+ MODEL_SERVER_URL = "http://model-server-url/predict"
30
+
31
+ @app.post("/save-audio")
32
+ async def save_audio(file: UploadFile = File(...)):
33
+ if not file.content_type.startswith('audio/'):
34
+ raise HTTPException(status_code=400, detail="Invalid file type")
35
+
36
+ file_path = os.path.join(UPLOAD_DIR, file.filename)
37
+
38
+ try:
39
+ with open(file_path, "wb") as f:
40
+ content = await file.read()
41
+ f.write(content)
42
+ return JSONResponse(content={"message": "File saved successfully", "filePath": file_path}, status_code=200)
43
+ except Exception as e:
44
+ return JSONResponse(content={"error": str(e)}, status_code=500)
45
+
46
+
47
+ model = tf.keras.models.load_model("cnn_1_v6_final_model.keras", compile=False)
48
+
49
+ @app.post("/process-audio")
50
+ async def process_audio(audio: UploadFile = File(...)):
51
+ if audio.content_type != "audio/mpeg":
52
+ raise HTTPException(status_code=400, detail="Invalid file type. Please upload an MP3 file.")
53
+
54
+ audio_bytes = await audio.read()
55
+
56
+ features = get_features(audio_bytes)
57
+
58
+ if features is None:
59
+ raise HTTPException(status_code=400, detail="Invalid audio file. Please upload a valid MP3 file.")
60
+
61
+ prediction = model.predict(np.expand_dims(features, axis=0))
62
+
63
+ return {"prediction": prediction}
64
+
65
+
66
+ '''
67
+ @router.post("/login")
68
+ async def login(user_data: UserLoginForm):
69
+ user = User.get(User.login == user_data.login)
70
+ if not user or user_data.password != user.password:
71
+ return {"message": "Invalid login or password"}
72
+ token_content = {"user_id": user.user_id}
73
+ jwt_token = jwt.encode(token_content, SECRET_KEY, algorithm=ALGORITHM)
74
+ return {"token": jwt_token}
75
+
76
+
77
+ @router.post("/registration")
78
+ async def registration(user_data: UserRegistration):
79
+ try:
80
+ new_user = User.create(login=user_data.login, password=user_data.password)
81
+ new_user.save()
82
+ return {"message": "User registered successfully"}
83
+ except IntegrityError:
84
+ return {"message": "User with this login already exists"}
85
+ '''
models.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from peewee import *
2
+
3
+ connection = SqliteDatabase('database.db')
4
+
5
+
6
+
7
+ class BaseModel(Model):
8
+ class Meta:
9
+ database = connection
10
+
11
+ class User(BaseModel):
12
+ user_id = AutoField()
13
+ login = CharField(unique=True)
14
+ password = CharField()
15
+
16
+ class Meta:
17
+ db_table = 'Users'
18
+ order_by = ('user_id',)
19
+
20
+
21
+ class Course(BaseModel):
22
+ course_id = AutoField()
23
+ name = CharField()
24
+ progress = IntegerField()
25
+
26
+ class Meta:
27
+ db_table = 'Courses'
28
+ order_by = ('course_id',)
29
+ from peewee import *
30
+
31
+ connection = SqliteDatabase('database.db')
32
+
33
+
34
+
35
+ class BaseModel(Model):
36
+ class Meta:
37
+ database = connection
38
+
39
+ class User(BaseModel):
40
+ user_id = AutoField()
41
+ login = CharField(unique=True)
42
+ password = CharField()
43
+
44
+ class Meta:
45
+ db_table = 'Users'
46
+ order_by = ('user_id',)
47
+
48
+
49
+ class Course(BaseModel):
50
+ course_id = AutoField()
51
+ name = CharField()
52
+ progress = IntegerField()
53
+
54
+ class Meta:
55
+ db_table = 'Courses'
56
+ order_by = ('course_id',)
requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ torch
4
+ librosa
5
+ requests
6
+ keras
7
+ requests
8
+ io
9
+ os
10
+ logging
11
+ tempfile
12
+ tensorflow
13
+ keras
server.log ADDED
File without changes
test.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import keras
4
+ import httpx
5
+ import librosa
6
+
7
+ from utils import (
8
+ extract_features,
9
+ pad_or_trim,
10
+ )
11
+
12
+ def test_get_answer(audio_file_path: str):
13
+ url = "http://127.0.0.1:8000/process-audio"
14
+ headers = {
15
+ "accept": "application/json",
16
+ }
17
+
18
+ with open(audio_file_path, "rb") as audio_file:
19
+ files = {
20
+ "audio": ("test.mp3", audio_file, "audio/mp3")
21
+ }
22
+ response = httpx.post(url, headers=headers, files=files)
23
+ print("Status Code:", response.status_code)
24
+ print("Response JSON:", response.json())
25
+
26
+
27
+ audio_file_path = "test_audio.mp3"
28
+ if not os.path.exists(audio_file_path):
29
+ raise FileNotFoundError(f"Audio file not found at {audio_file_path}")
30
+
31
+ audio_data, sample_rate = librosa.load(audio_file_path)
32
+
33
+ features = extract_features(audio_data, sample_rate)
34
+
35
+ target_shape = (32, 200)
36
+ features = pad_or_trim(features, target_shape[1])
37
+
38
+
39
+ features = np.expand_dims(features, axis=0)
40
+
41
+ filepath = os.path.abspath("cnn_1_v6_final_model.h5")
42
+ if not os.path.exists(filepath):
43
+ raise FileNotFoundError(f"Model file not found at {filepath}")
44
+
45
+ model = keras.models.load_model(filepath, compile=False)
46
+
47
+
48
+ prediction = model.predict(features)
49
+ print(f"Prediction: {prediction.tolist()}")
50
+
51
+ test_get_answer(audio_file_path)
test_audio.mp3 ADDED
Binary file (2.71 kB). View file
 
utils.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <<<<<<< HEAD
2
+ import librosa
3
+ import numpy as np
4
+ from keras import layers, models
5
+
6
+ def create_cnn_model(input_shape):
7
+ model = models.Sequential()
8
+
9
+ # First Convolutional Layer
10
+ model.add(layers.Conv1D(32, 3, activation='relu', input_shape=input_shape))
11
+ model.add(layers.MaxPooling1D(pool_size=2))
12
+
13
+ # Second Convolutional Layer
14
+ model.add(layers.Conv1D(64, 3, activation='relu'))
15
+ model.add(layers.MaxPooling1D(pool_size=2))
16
+
17
+ # Flatten layer
18
+ model.add(layers.Flatten())
19
+
20
+ # Dense layers
21
+ model.add(layers.Dense(128, activation='relu', input_shape=input_shape))
22
+ model.add(layers.Dense(256, activation='relu', input_shape=input_shape))
23
+ model.add(layers.Dense(512, activation='relu', input_shape=input_shape))
24
+ model.add(layers.Dense(512, activation='relu', input_shape=input_shape))
25
+ model.add(layers.Dense(256, activation='relu', input_shape=input_shape))
26
+ model.add(layers.Dense(128, activation='relu', input_shape=input_shape))
27
+
28
+ # Output layer
29
+ model.add(layers.Dense(1, activation='sigmoid'))
30
+
31
+ return model
32
+
33
+
34
+ def get_features(path, duration=6):
35
+ try:
36
+ # Load audio file with specific duration and offset to handle silent parts
37
+ data, sample_rate = librosa.load(path, duration=2.5, offset=0.6)
38
+ except Exception as e:
39
+ print(f"Error loading {path}: {e}")
40
+ return None # Skip the file if there's an error
41
+
42
+ # Without augmentation
43
+ res1 = extract_features(data, sample_rate)
44
+ result = np.array(res1)
45
+
46
+ # With noise
47
+ noise_data = noise(data)
48
+ res2 = extract_features(noise_data, sample_rate)
49
+ result = np.vstack((result, res2))
50
+
51
+ # Stretching and pitching
52
+ new_data = stretch(data)
53
+ data_stretch_pitch = pitch(new_data, sample_rate)
54
+ res3 = extract_features(data_stretch_pitch, sample_rate)
55
+ result = np.vstack((result, res3))
56
+
57
+ return result
58
+
59
+
60
+ def extract_features(data, sample_rate, target_shape=40):
61
+ result = np.array([])
62
+
63
+ # ZCR
64
+ zcr = librosa.feature.zero_crossing_rate(y=data)
65
+ zcr = np.mean(zcr.T, axis=0)
66
+ zcr = pad_or_trim(zcr, target_shape)
67
+ result = np.hstack((result, zcr))
68
+
69
+ # Chroma_stft
70
+ stft = np.abs(librosa.stft(data))
71
+ chroma_stft = librosa.feature.chroma_stft(S=stft, sr=sample_rate)
72
+ chroma_stft = np.mean(chroma_stft.T, axis=0)
73
+ chroma_stft = pad_or_trim(chroma_stft, target_shape)
74
+ result = np.hstack((result, chroma_stft))
75
+
76
+ # MFCC
77
+ mfcc = librosa.feature.mfcc(y=data, sr=sample_rate, n_mfcc=13)
78
+ mfcc = np.mean(mfcc.T, axis=0)
79
+ mfcc = pad_or_trim(mfcc, target_shape)
80
+ result = np.hstack((result, mfcc))
81
+
82
+ # Root Mean Square Value
83
+ rms = librosa.feature.rms(y=data)
84
+ rms = np.mean(rms.T, axis=0)
85
+ rms = pad_or_trim(rms, target_shape)
86
+ result = np.hstack((result, rms))
87
+
88
+ # MelSpectrogram
89
+ mel = librosa.feature.melspectrogram(y=data, sr=sample_rate)
90
+ mel = np.mean(mel.T, axis=0)
91
+ mel = pad_or_trim(mel, target_shape)
92
+ result = np.hstack((result, mel))
93
+
94
+ return result
95
+
96
+
97
+ def pad_or_trim(feature, target_shape):
98
+ """Pad or trim feature array to ensure a consistent shape."""
99
+ if len(feature) > target_shape:
100
+ feature = feature[:target_shape]
101
+ elif len(feature) < target_shape:
102
+ feature = np.pad(feature, (0, target_shape - len(feature)), mode='constant')
103
+ return feature
104
+
105
+
106
+ def noise(data, noise_factor=0.005):
107
+ noise_amp = noise_factor * np.random.uniform() * np.amax(data)
108
+ data = data + noise_amp * np.random.normal(size=data.shape[0])
109
+ return data
110
+
111
+ def stretch(data, rate=0.8):
112
+ return librosa.effects.time_stretch(data, rate=rate)
113
+
114
+ def pitch(data, sample_rate, pitch_factor=0.7):
115
+ return librosa.effects.pitch_shift(data, sr=sample_rate, n_steps=pitch_factor)
116
+
117
+
118
+
119
+ =======
120
+ import librosa
121
+ import numpy as np
122
+ from keras import layers, models
123
+
124
+ def create_cnn_model(input_shape):
125
+ model = models.Sequential()
126
+
127
+ # First Convolutional Layer
128
+ model.add(layers.Conv1D(32, 3, activation='relu', input_shape=input_shape))
129
+ model.add(layers.MaxPooling1D(pool_size=2))
130
+
131
+ # Second Convolutional Layer
132
+ model.add(layers.Conv1D(64, 3, activation='relu'))
133
+ model.add(layers.MaxPooling1D(pool_size=2))
134
+
135
+ # Flatten layer
136
+ model.add(layers.Flatten())
137
+
138
+ # Dense layers
139
+ model.add(layers.Dense(128, activation='relu', input_shape=input_shape))
140
+ model.add(layers.Dense(256, activation='relu', input_shape=input_shape))
141
+ model.add(layers.Dense(512, activation='relu', input_shape=input_shape))
142
+ model.add(layers.Dense(512, activation='relu', input_shape=input_shape))
143
+ model.add(layers.Dense(256, activation='relu', input_shape=input_shape))
144
+ model.add(layers.Dense(128, activation='relu', input_shape=input_shape))
145
+
146
+ # Output layer
147
+ model.add(layers.Dense(1, activation='sigmoid'))
148
+
149
+ return model
150
+
151
+
152
+ def get_features(path, duration=6):
153
+ try:
154
+ # Load audio file with specific duration and offset to handle silent parts
155
+ data, sample_rate = librosa.load(path, duration=2.5, offset=0.6)
156
+ except Exception as e:
157
+ print(f"Error loading {path}: {e}")
158
+ return None # Skip the file if there's an error
159
+
160
+ # Without augmentation
161
+ res1 = extract_features(data, sample_rate)
162
+ result = np.array(res1)
163
+
164
+ # With noise
165
+ noise_data = noise(data)
166
+ res2 = extract_features(noise_data, sample_rate)
167
+ result = np.vstack((result, res2))
168
+
169
+ # Stretching and pitching
170
+ new_data = stretch(data)
171
+ data_stretch_pitch = pitch(new_data, sample_rate)
172
+ res3 = extract_features(data_stretch_pitch, sample_rate)
173
+ result = np.vstack((result, res3))
174
+
175
+ return result
176
+
177
+
178
+ def extract_features(data, sample_rate, target_shape=40):
179
+ result = np.array([])
180
+
181
+ # ZCR
182
+ zcr = librosa.feature.zero_crossing_rate(y=data)
183
+ zcr = np.mean(zcr.T, axis=0)
184
+ zcr = pad_or_trim(zcr, target_shape)
185
+ result = np.hstack((result, zcr))
186
+
187
+ # Chroma_stft
188
+ stft = np.abs(librosa.stft(data))
189
+ chroma_stft = librosa.feature.chroma_stft(S=stft, sr=sample_rate)
190
+ chroma_stft = np.mean(chroma_stft.T, axis=0)
191
+ chroma_stft = pad_or_trim(chroma_stft, target_shape)
192
+ result = np.hstack((result, chroma_stft))
193
+
194
+ # MFCC
195
+ mfcc = librosa.feature.mfcc(y=data, sr=sample_rate, n_mfcc=13)
196
+ mfcc = np.mean(mfcc.T, axis=0)
197
+ mfcc = pad_or_trim(mfcc, target_shape)
198
+ result = np.hstack((result, mfcc))
199
+
200
+ # Root Mean Square Value
201
+ rms = librosa.feature.rms(y=data)
202
+ rms = np.mean(rms.T, axis=0)
203
+ rms = pad_or_trim(rms, target_shape)
204
+ result = np.hstack((result, rms))
205
+
206
+ # MelSpectrogram
207
+ mel = librosa.feature.melspectrogram(y=data, sr=sample_rate)
208
+ mel = np.mean(mel.T, axis=0)
209
+ mel = pad_or_trim(mel, target_shape)
210
+ result = np.hstack((result, mel))
211
+
212
+ return result
213
+
214
+
215
+ def pad_or_trim(feature, target_shape):
216
+ """Pad or trim feature array to ensure a consistent shape."""
217
+ if len(feature) > target_shape:
218
+ feature = feature[:target_shape]
219
+ elif len(feature) < target_shape:
220
+ feature = np.pad(feature, (0, target_shape - len(feature)), mode='constant')
221
+ return feature
222
+
223
+
224
+ def noise(data, noise_factor=0.005):
225
+ noise_amp = noise_factor * np.random.uniform() * np.amax(data)
226
+ data = data + noise_amp * np.random.normal(size=data.shape[0])
227
+ return data
228
+
229
+ def stretch(data, rate=0.8):
230
+ return librosa.effects.time_stretch(data, rate=rate)
231
+
232
+ def pitch(data, sample_rate, pitch_factor=0.7):
233
+ return librosa.effects.pitch_shift(data, sr=sample_rate, n_steps=pitch_factor)
234
+
235
+
236
+
237
+ >>>>>>> f3090616676ed6b7fcf9d16589c788e1843b194c