# -*- coding: utf-8 -*-
"""27%NLP_PROJECT_rnn.ipynb

Automatically generated by Colab.

Original file is located at
    https://colab.research.google.com/drive/1ZdzAVjrcHeK1QpehyRV85JD_FzNdOifg
"""

#dataset
import os
os.environ['KAGGLE_CONFIG_DIR'] = "/content"

!kaggle datasets download -d ejlok1/toronto-emotional-speech-set-tess

!unzip \*.zip  && rm *.zip

# Import necessary modules
import pandas as pd
import numpy as np
import os
import seaborn as sns
import matplotlib.pyplot as plt
import librosa
import librosa.display
from IPython.display import Audio
import warnings
warnings.filterwarnings('ignore')

# Load the dataset
paths = []
labels = []
for dirname, _, filenames in os.walk('/content/TESS Toronto emotional speech set data'):
    for filename in filenames:
        paths.append(os.path.join(dirname, filename))
        label = filename.split('_')[-1]
        label = label.split('.')[0]
        labels.append(label.lower())
    if len(paths) == 2800:
        break
print('Dataset is Loaded')

# Check dataset length and sample paths
print(f'Number of samples: {len(paths)}')
print('Sample paths:', paths[:5])
print('Sample labels:', labels[:5])

# Create a dataframe
df = pd.DataFrame()
df['speech'] = paths
df['label'] = labels
print(df.head())
print(df['label'].value_counts())

# Exploratory Data Analysis
sns.countplot(data=df, x='label')
plt.show()

def waveplot(data, sr, emotion):
    plt.figure(figsize=(10,4))
    plt.title(emotion, size=20)
    librosa.display.waveshow(data, sr=sr)
    plt.show()

def spectogram(data, sr, emotion):
    x = librosa.stft(data)
    xdb = librosa.amplitude_to_db(abs(x))
    plt.figure(figsize=(11,4))
    plt.title(emotion, size=20)
    librosa.display.specshow(xdb, sr=sr, x_axis='time', y_axis='hz')
    plt.colorbar()
    plt.show()

# Display sample audio waves and spectrograms
emotions = ['fear', 'angry', 'disgust', 'neutral', 'sad', 'ps', 'happy']
for emotion in emotions:
    path = np.array(df['speech'][df['label']==emotion])[0]
    data, sampling_rate = librosa.load(path)
    waveplot(data, sampling_rate, emotion)
    spectogram(data, sampling_rate, emotion)
    display(Audio(path))

# Feature Extraction
def extract_mfcc(filename):
    y, sr = librosa.load(filename, duration=3, offset=0.5)
    mfcc = np.mean(librosa.feature.mfcc(y=y, sr=sr, n_mfcc=40).T, axis=0)
    return mfcc

# Extract MFCC features
X_mfcc = df['speech'].apply(lambda x: extract_mfcc(x))
X = np.array([x for x in X_mfcc])
X = np.expand_dims(X, -1)
print('MFCC shape:', X.shape)

# One-hot encoding labels
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder()
y = enc.fit_transform(df[['label']])
y = y.toarray()
print('One-hot encoded labels shape:', y.shape)

# Create the LSTM model
from keras.models import Sequential
from keras.layers import Dense, LSTM, Dropout

model = Sequential([
    LSTM(256, return_sequences=False, input_shape=(40,1)),
    Dropout(0.2),
    Dense(128, activation='relu'),
    Dropout(0.2),
    Dense(64, activation='relu'),
    Dropout(0.2),
    Dense(7, activation='softmax')
])

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

# Train the model
history = model.fit(X, y, validation_split=0.2, epochs=50, batch_size=64)

# Plot results
epochs = list(range(50))
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

plt.figure(figsize=(12, 6))
plt.plot(epochs, acc, label='train accuracy')
plt.plot(epochs, val_acc, label='val accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()

loss = history.history['loss']
val_loss = history.history['val_loss']

plt.figure(figsize=(12, 6))
plt.plot(epochs, loss, label='train loss')
plt.plot(epochs, val_loss, label='val loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()

model.save('/content/model_rnn.h5')

# Final training and validation accuracy
train_acc = history.history['accuracy'][-1]
val_acc = history.history['val_accuracy'][-1]

print(f'Final training accuracy: {train_acc * 100:.2f}%')
print(f'Final validation accuracy: {val_acc * 100:.2f}%')

# Load and preprocess the new audio file
def preprocess_audio(file_path):
    # Extract MFCC features from the new audio file
    mfcc_features = extract_mfcc(file_path)
    mfcc_features = np.expand_dims(mfcc_features, axis=0)  # Shape should be (1, 40)
    mfcc_features = np.expand_dims(mfcc_features, axis=-1)  # Shape should be (1, 40, 1)
    return mfcc_features

# Predict the emotion of the new audio file
def predict_emotion(file_path, model):
    preprocessed_audio = preprocess_audio(file_path)
    prediction = model.predict(preprocessed_audio)
    predicted_label_index = np.argmax(prediction, axis=1)[0]
    return enc.categories_[0][predicted_label_index]

# Test with a new file (MP3 file path)
new_file_path = '/content/zzz01j79-fm6wj-5mw42-3bbzz-x45618.mp3'  # Replace with your MP3 file path
predicted_emotion = predict_emotion(new_file_path, model)
print(f'The predicted emotion for the new file is: {predicted_emotion}') in this i want to increases the accuracy of my model use hyper parameter and give me code