This commit is contained in:
gpt-engineer-app[bot] 2025-12-21 15:18:54 +00:00
parent 6693f94b65
commit 64fec848fe
2 changed files with 113 additions and 108 deletions

View File

@ -157,7 +157,7 @@ export function MiniOscilloscope() {
return ( return (
<div <div
onClick={handleClick} onClick={handleClick}
className="fixed bottom-6 left-1/2 -translate-x-1/2 w-[400px] md:w-[600px] h-[80px] z-50 cursor-pointer group" className="fixed bottom-6 left-1/2 -translate-x-1/2 w-[200px] h-[50px] md:w-[600px] md:h-[80px] z-50 cursor-pointer group"
title="Open Oscilloscope" title="Open Oscilloscope"
> >
<div className="relative w-full h-full rounded-lg border border-primary/50 overflow-hidden bg-background/80 backdrop-blur-sm transition-all duration-300 group-hover:border-primary group-hover:shadow-[0_0_20px_hsl(var(--primary)/0.4)]"> <div className="relative w-full h-full rounded-lg border border-primary/50 overflow-hidden bg-background/80 backdrop-blur-sm transition-all duration-300 group-hover:border-primary group-hover:shadow-[0_0_20px_hsl(var(--primary)/0.4)]">

View File

@ -247,7 +247,7 @@ export function Oscilloscope() {
const canGenerate = audioData !== null && originalFile !== null && !isExporting && !isLoading; const canGenerate = audioData !== null && originalFile !== null && !isExporting && !isLoading;
return ( return (
<div className="space-y-6 max-w-6xl mx-auto"> <div className="space-y-6 max-w-7xl mx-auto">
{/* Header */} {/* Header */}
<div className="text-center space-y-4"> <div className="text-center space-y-4">
<h2 className="font-minecraft text-2xl md:text-3xl text-primary text-glow-strong"> <h2 className="font-minecraft text-2xl md:text-3xl text-primary text-glow-strong">
@ -258,130 +258,135 @@ export function Oscilloscope() {
</p> </p>
</div> </div>
{/* Controls Row */} {/* Audio Input Row */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6"> <div className="flex flex-col sm:flex-row items-start sm:items-center gap-4">
{/* Left Column: Audio Input */} <div className="flex-1 w-full sm:w-auto">
<div className="space-y-4">
<AudioUploader <AudioUploader
onFileSelect={handleFileSelect} onFileSelect={handleFileSelect}
isLoading={isLoading} isLoading={isLoading}
fileName={fileName} fileName={fileName}
/> />
{/* Microphone Toggle */}
<div className="flex items-center gap-4">
<Button
onClick={toggleMic}
variant={isMicActive ? "default" : "outline"}
className={`flex items-center gap-2 font-crt ${
isMicActive
? 'bg-primary text-primary-foreground'
: 'border-primary/50 hover:bg-primary/10'
}`}
>
{isMicActive ? <MicOff size={16} /> : <Mic size={16} />}
{isMicActive ? 'STOP MIC' : 'USE MICROPHONE'}
</Button>
{isMicActive && (
<div className="flex items-center gap-4">
<div className="text-sm text-muted-foreground font-mono-crt">
Real-time input active
</div>
<Button
onClick={() => setShowMicCalibration(!showMicCalibration)}
variant="outline"
size="sm"
className="font-mono-crt text-xs"
>
Calibrate
</Button>
</div>
)}
</div>
</div> </div>
{/* Right Column: Control Panel */} {/* Microphone Toggle */}
<OscilloscopeControls <div className="flex items-center gap-4">
mode={mode} <Button
onModeChange={setMode} onClick={toggleMic}
canGenerate={canGenerate} variant={isMicActive ? "default" : "outline"}
isGenerating={isExporting} className={`flex items-center gap-2 font-crt ${
progress={progress} isMicActive
exportedUrl={exportedUrl} ? 'bg-primary text-primary-foreground'
onGenerate={handleGenerate} : 'border-primary/50 hover:bg-primary/10'
onReset={handleReset} }`}
isPlaying={isPlaying} >
onPreview={handlePreview} {isMicActive ? <MicOff size={16} /> : <Mic size={16} />}
canPreview={canPreview} {isMicActive ? 'STOP MIC' : 'USE MICROPHONE'}
playbackSpeed={playbackSpeed} </Button>
onPlaybackSpeedChange={handlePlaybackSpeedChange}
isLooping={isLooping}
onLoopingChange={handleLoopingChange}
exportResolution={exportResolution}
onExportResolutionChange={handleExportResolutionChange}
exportFps={exportFps}
onExportFpsChange={handleExportFpsChange}
exportQuality={exportQuality}
onExportQualityChange={handleExportQualityChange}
liveSettings={liveSettings}
onLiveSettingsChange={setLiveSettings}
/>
</div>
{/* Oscilloscope Display */} {isMicActive && (
<div className="flex justify-center flex-col items-center gap-4">
<OscilloscopeDisplay
audioData={audioData}
micAnalyzer={micAnalyzer}
mode={liveSettings.displayMode}
isPlaying={isPlaying}
playbackSpeed={playbackSpeed}
isLooping={isLooping}
audioElementRef={audioRef}
onPlaybackEnd={() => {
setIsPlaying(false);
setCurrentTime(0);
setSeekPosition(0);
}}
onSeek={handleSeek}
liveSettings={liveSettings}
/>
{/* Audio Playback Controls */}
{audioData && originalFile && (
<div className="w-full max-w-3xl space-y-2 px-4">
{/* Play/Pause and Time Display */}
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="text-sm text-muted-foreground font-mono-crt">
Real-time input active
</div>
<Button <Button
onClick={handlePreview} onClick={() => setShowMicCalibration(!showMicCalibration)}
variant="outline" variant="outline"
size="sm" size="sm"
className="font-crt border-primary/50 hover:bg-primary/10" className="font-mono-crt text-xs"
disabled={isExporting}
> >
{isPlaying ? <Pause size={16} /> : <Play size={16} />} Calibrate
</Button> </Button>
</div>
)}
</div>
</div>
<span className="font-mono-crt text-sm text-foreground/80 min-w-[80px]"> {/* Main Content: Display + Controls Side by Side */}
{formatTime(currentTime)} / {formatTime(audioData.duration)} <div className="grid grid-cols-1 xl:grid-cols-[1fr_320px] gap-6">
</span> {/* Oscilloscope Display */}
<div className="flex flex-col items-center gap-4 order-2 xl:order-1">
<OscilloscopeDisplay
audioData={audioData}
micAnalyzer={micAnalyzer}
mode={liveSettings.displayMode}
isPlaying={isPlaying}
playbackSpeed={playbackSpeed}
isLooping={isLooping}
audioElementRef={audioRef}
onPlaybackEnd={() => {
setIsPlaying(false);
setCurrentTime(0);
setSeekPosition(0);
}}
onSeek={handleSeek}
liveSettings={liveSettings}
/>
{/* Progress Bar */} {/* Audio Playback Controls */}
<div className="flex-1"> {audioData && originalFile && (
<Slider <div className="w-full max-w-3xl space-y-2 px-4">
value={[seekPosition * 100]} {/* Play/Pause and Time Display */}
onValueChange={(value) => handleSeek(value[0] / 100)} <div className="flex items-center gap-4">
max={100} <Button
step={0.1} onClick={handlePreview}
className="cursor-pointer" variant="outline"
/> size="sm"
className="font-crt border-primary/50 hover:bg-primary/10"
disabled={isExporting}
>
{isPlaying ? <Pause size={16} /> : <Play size={16} />}
</Button>
<span className="font-mono-crt text-sm text-foreground/80 min-w-[80px]">
{formatTime(currentTime)} / {formatTime(audioData.duration)}
</span>
{/* Progress Bar */}
<div className="flex-1">
<Slider
value={[seekPosition * 100]}
onValueChange={(value) => handleSeek(value[0] / 100)}
max={100}
step={0.1}
className="cursor-pointer"
/>
</div>
</div> </div>
</div> </div>
</div> )}
)} </div>
{/* Control Panel */}
<div className="order-1 xl:order-2">
<OscilloscopeControls
mode={mode}
onModeChange={setMode}
canGenerate={canGenerate}
isGenerating={isExporting}
progress={progress}
exportedUrl={exportedUrl}
onGenerate={handleGenerate}
onReset={handleReset}
isPlaying={isPlaying}
onPreview={handlePreview}
canPreview={canPreview}
playbackSpeed={playbackSpeed}
onPlaybackSpeedChange={handlePlaybackSpeedChange}
isLooping={isLooping}
onLoopingChange={handleLoopingChange}
exportResolution={exportResolution}
onExportResolutionChange={handleExportResolutionChange}
exportFps={exportFps}
onExportFpsChange={handleExportFpsChange}
exportQuality={exportQuality}
onExportQualityChange={handleExportQualityChange}
liveSettings={liveSettings}
onLiveSettingsChange={setLiveSettings}
/>
</div>
</div> </div>
{/* Microphone Calibration */} {/* Microphone Calibration */}
{showMicCalibration && isMicActive && ( {showMicCalibration && isMicActive && (
<div className="bg-card border border-border rounded-lg p-4 max-w-md mx-auto"> <div className="bg-card border border-border rounded-lg p-4 max-w-md mx-auto">